精华内容
下载资源
问答
  • 主要介绍了PHP基于面向对象实现的留言本功能,结合实例形式分析了php基于面向对象留言本相关写入、显示查看、日志记录等相关方法封装与使用技巧,需要的朋友可以参考下
  • 内容索引:.NET源码,其它类别,Session,留言 利用Session对象制作留言或意见反馈程序,没有数据库,只是练习Session对象的使用,将表单的数据通过Session临时保存,如果结合数据库,就轻易实现了留言本程序。
  • 使用samrty模版制作的简单留言板 适合初学者浏览,其中使用了面向对象
  • 简单的应用了一下面向对象写的一个新闻列表,也可以说是留言板吧,其中包含了一些基本数据库的操作。
  • php留言本系统,简单的采用了面向对象编程
  • Asp.net简单留言板源码(采用面向对象开发) 可以对留言进行回复 游客也可以留言,用户登录采用随机验证码 该示例采用面向对象方法开发
  • Asp.net简单留言板源码(采用面向对象开发,包含所有CS文件) <br>可以对留言进行回复 游客也可以留言,用户登录采用随机验证码 默认帐号密码51aspx 该示例采用面向对象方法开发 <br>该源码为...
  • //实例化一个数据库连接对象 $db = new DB('localhost','3306','liuyanban','root','v7F5y6n4'); //遍历查询结果集 if ($result = $db->get_all('liuyanban')) { while ($row = $result->fetch_assoc()) { ...
  • 实现了实体类的自动加载,只需在model实例化时传入一个实体类名,即可实现实体类与数据库表的绑定 使用对象容器,在查询出结果集之后,直接...model中不应该定义数据库相关的变量操作 效果: 源码目录结构: Mod
    • 实现了实体类的自动加载,只需在model实例化时传入一个实体类名,即可实现实体类与数据库表的绑定
    • 使用对象容器,在查询出结果集之后,直接生成对象并放入对象容器
    • 取实体类数据时,会返回一个对象容器,遍历转换成对象数组并进行json编码,打印到页面就成了API
    • 界面使用css绘制按钮,输入框
    • 使用数据库配置文件
    • 前后端分离
    • model中不应该定义数据库相关的变量和操作

    code:
    https://code.csdn.net/u012995856/oop_liuyanban/tree/master

    效果:
    这里写图片描述

    源码目录结构:
    这里写图片描述

    Model.php

    <?php
    /**
     *模型类,介于实体类与数据库表之间的存在,是拥有数据的实体类集合
     *
     */
    require 'DB.php';
    
    class Model
    {
      private $obj;
      private static $entity_name;
      private $db;
      private $container;
    
      //构造方法
      //根据实例化Model时的传入参数
      //自动加载实体类,并实例化
      function __construct($entity){
    
        $this->entity_name = $entity;//暂存实体类类名
    
        $this->db = new DB;
    
        set_include_path('./');//设置自动加载目录
        spl_autoload_register();//自动加载
    
        $this->obj = new $entity;//实例化实体类
    
      }
    
      //根据模型自动查询数据,将结果集对象化到容器,返回对象容器
      public function get_all(){
        $sql = 'select * from '.$this->entity_name;
        $result = $this->db->query($sql);
    
        $container = new SplObjectStorage();//实例化对象容器
    
        while ($entity_obj = $result->fetch_object()) {
            $container->attach($entity_obj);
        }
    
        return $container;
      }
    
    
    
    }
    

    DB.conf.php

    <?php
    //定义数据库配置 
    
    define('HOST', 'localhost');
    define('PORT', '3306');
    define('USER', 'root');
    define('PASSWORD', '123456');
    define('DB_NAME', 'liuyanban');
    

    DB.php

    <?php
    /**
     *数据库类
     *提供基础的数据库操作
     */
    
    require 'DB.conf.php';
    
    class DB
    {
      //定义数据库变量
      private static $host = HOST;
      private static $port = PORT;
      private static $db_name = DB_NAME;
      private static $user_name = USER;
      private static $user_password = PASSWORD;
      private $mysqli;
      private $result;
    
      //构造方法,用于实例化数据库对象时创建一个数据库连接
      function __construct(){
        $this->mysqli = new mysqli(
              HOST,
              USER,
              PASSWORD,
              DB_NAME
        );
        if ($this->mysqli->connect_error) {
          die('database connect error!');
        }
        //析构方法,用于实例销毁时关闭数据库连接
        function __desstruct(){
          $this->mysqli->close();
          $this->result->close();
        }
        //设置编码集
        $this->mysqli->query('set names utf8');
      }
      //查询方法
      public function query($sql){
        $this->result = $this->mysqli->query($sql);
        return $this->result;
      }
      //
      public function get_one($table,$key,$value){
    
      }
    
      public function get_some(){
    
      }
    
    public function get_all_objs($value='')
    {
      # code...
    }
    
    public function get_all_arr($value='')
    {
      # code...
    }
    
      //根据单个条件进行查询
      public function get_all_by_condition($value=''){
        # code...
      }
      //根据符合条件进行查询
      public function get_all_by_conditions($value=''){
        # code...
      }
    
    
    
    
    }
    

    getdata.php

    <?php
    require 'Model.php';
    /**
     *获取留言板数据,类似于Controller
     *
     */
    
    
    $model = new Model('liuyanban');
    $container = $model->get_all();
    $arr = array();
    
    
    $container->rewind();
    while ($container->valid()) {
      $arr[] = $container->current();
      $container->next();
    }
    
    //var_dump($arr);
    
    echo json_encode($arr);
    

    LiuYanBan.php

    <?php
    /**
     *
     */
    class liuyanban
    {
      //成员变量
      //对应数据库表的字段
      private static $lyb_id;
      private static $lyb_title;
      private static $lyb_content;
      private static $lyb_author;
      private static $lyb_time;
      private static $lyb_authoremail;
      private static $lyb_pass;
    
      //构造方法
      function __construct(){
        //echo '创建了一个留言板<br>';
        }
    
    }
    

    index.html

    <!DOCTYPE html>
    <html>
      <head>
    
        <meta charset="utf-8">
        <title>留言板</title>
        <link rel="stylesheet" href="index.css" media="screen" title="no title" charset="utf-8">
        <script src="http://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
      </head>
      <body>
    <div class="lyb">
      <h1>留言板 </h1>
    <div class="lyb-add">
      <input name="name" />
    <button type="button" name="button">留言</button>
    </div>
    <br><br>
    <div class="lyb-list" id="lyb-list">
    
    </div>
    </div>
    
      </body>
      <script type="text/javascript">
        $(function(){
          $.get("http://localhost/liuyanban/getlybdata.php",function(data,status) {
          //  var lyb = $.parsejson(data);
          var objs = eval(data);
          var content = '<table>';
          $.each(objs,function(i,item) {
            content += '<tr><th>'+item.lyb_title+' '+item.lyb_author+'<br><br>'+item.lyb_content+'<br>'+item.lyb_authoremail+'<br><br><hr></th></tr>';
          });
          content+='</table>';
          $('#lyb-list').html(content);
          });
        }
        );
      </script>
    </html>
    

    index.css

    .lyb  .lyb-add  button{
      background-color: #4CAF50; /* Green */
        border: none;
        color: white;
        padding: 5px 20px;
        text-align: center;
        text-decoration: none;
        display: inline-block;
        font-size: 16px;
        border-radius: 8px;
    }
    
    .lyb .lyb-add input{
      background: #fff; border: 1px solid #000;
      padding: 5px;
      border-radius: 5px;
      -webkit-border-radius: 5px;
      -moz-border-radius: 5px;
    }
    
    .lyb{
      text-align: center;
    }
    
    .lyb .lyb-list table{
      text-align: center;
      margin:auto;
    }
    

    liuyanban.sql

    -- phpMyAdmin SQL Dump
    -- version phpStudy 2014
    -- http://www.phpmyadmin.net
    --
    -- 主机: localhost
    -- 生成日期: 2016 广08 朿22 旿20:54
    -- 服务器版本: 5.5.47
    -- PHP 版本: 5.5.30
    
    SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
    SET time_zone = "+00:00";
    
    
    /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
    /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
    /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
    /*!40101 SET NAMES utf8 */;
    
    --
    -- 数据库: `liuyanban`
    --
    
    -- --------------------------------------------------------
    
    --
    -- 表的结构 `liuyanban`
    --
    
    CREATE TABLE IF NOT EXISTS `liuyanban` (
      `lyb_id` varchar(255) NOT NULL,
      `lyb_title` varchar(255) NOT NULL,
      `lyb_content` varchar(255) NOT NULL,
      `lyb_author` varchar(50) NOT NULL,
      `lyb_time` varchar(255) NOT NULL,
      `lyb_authoremail` varchar(50) NOT NULL,
      `lyb_pass` int(11) NOT NULL,
      UNIQUE KEY `lyb_id` (`lyb_id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
    
    --
    -- 转存表中的数据 `liuyanban`
    --
    
    INSERT INTO `liuyanban` (`lyb_id`, `lyb_title`, `lyb_content`, `lyb_author`, `lyb_time`, `lyb_authoremail`, `lyb_pass`) VALUES
    ('c4ca4238a0b923820dcc509a6f75849b', '我的第一条留言', '留言的内容', 'pangPython', '12333112', 'pangpython@qq.com', 0),
    ('c81e728d9d4c2f636f067f89cc14862c', 'php面向对象留言板', '这是一个面向对象的留言板程序。。。。', 'pangPython', '8987879456', 'pangPython@qq.com', 1);
    
    /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
    /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
    /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
    

    前端可以使用一些框架,或者jquery 的数据表格json数据绑定更方便

    展开全文
  • 目前面向对象的语言有很多,Objective-C中的对象其他语言中的对象有什么区别呢?下面来简单介绍Objective-C中对象的实现。 1、Objective-C中的类 谁都知道,所有的对象都是由其对应的类实例化而来,殊不知类本身...

    Objective-C对象之类对象和元类对象(一)

    作者:wangzz
    转载请注明出处
    如果觉得文章对你有所帮助,请通过留言或关注微信公众帐号wangzzstrive来支持我,谢谢!

    作为C语言的超集,面向对象成为Objective-C与C语言的最大区别,因此,对象是Objective-C中最重要的部分之一。目前面向对象的语言有很多,Objective-C中的对象又和其他语言中的对象有什么区别呢?下面来简单介绍Objective-C中对象的实现。
    1、Objective-C中的类

    谁都知道,所有的对象都是由其对应的类实例化而来,殊不知类本身也是一种对象,先不要对这句话感到惊讶。
    首先我们来关注Objective-C中的类。在Objective-C中,我们用到的几乎所有类都是NSObject类的子类,NSObject类定义格式如下(忽略其方法声明):
    @interface NSObject <NSObject> {
    Class isa;
    }
    这个Class为何物?在objc.h中我们发现其仅仅是一个结构(struct)指针的typedef定义:
    typedef struct objc_class *Class;
    同样的,objc_class又是什么呢?在Objective-C2.0中,objc_class的定义如下:
    struct objc_class {
    Class isa;
    }
    写到这里大家可能就晕了,怎么又有一个isa??这些isa到底是什么?之间有什么区别和联系?接下来解答这一连串的疑问。
    其实在Objective-C中任何的类定义都是对象。即在程序启动的时候任何类定义都对应于一块内存。在编译的时候,编译器会给每一个类生成一个且只生成一个”描述其定义的对象”,也就是苹果公司说的类对象(class object),他是一个单例(singleton), 而我们在C++等语言中所谓的对象,叫做实例对象(instance object)。对于实例对象我们不难理解,但类对象(class object)是干什么吃的呢?我们知道Objective-C是门很动态的语言,因此程序里的所有实例对象(instace object)都是在运行时由Objective-C的运行时库生成的,而这个类对象(class object)就是运行时库用来创建实例对象(instance object)的依据。
    再回到之前的问题,肿么这个实例对象(instance object)的isa指针指向的类对象(class object)里面还有一个isa呢?这个类对象(class objec)的isa指向的依然是一个objc-class,它就是“元类对象”(metaclass object),它和类对象(class object)的关系是这样的:

    2、类对象(class object)
    ①类对象的实质
    我们知道了:类对象是由编译器创建的,即在编译时所谓的类,就是指类对象(官方文档中是这样说的: The class object is the compiled version of the class)。任何直接或间接继承了NSObject的类,它的实例对象(instance objec)中都有一个isa指针,指向它的类对象(class object)。这个类对象(class object)中存储了关于这个实例对象(instace object)所属的类的定义的一切:包括变量,方法,遵守的协议等等。因此,类对象能访问所有关于这个类的信息,利用这些信息可以产生一个新的实例,但是类对象不能访问任何实例对象的内容。
    当你调用一个 “类方法” 例如 [NSObject alloc],你事实上是发送了一个消息给他的类对象。

    ②类对象和实例对象的区别
    当然有区别了,尽管类对象保留了一个类实例的原型,但它并不是实例本身。它没有自己的实例变量,也不能执行那些类的实例的方法(只有实例对象才可以执行实例方法)。然而,类的定义能包含那些特意为类对象准备的方法–类方法( 而不是的实例方法)。类对象从父类那里继承类方法,就像实例从父类那里继承实例方法一样。
    ③类对象与类名
    在源代码中,类对象由类名表示。
    在下面的例子中,Retangle类 用从NSObject那里继承来的方法来返回类的版本号:
    int versionNumber = [Rectangle version];
    只有在消息表达式中作为接收者,类名才代表类对象。其他地方,你需要要求一个实例或者类返回class id。 响应class消息:
    id aClass = [anObject class];
    id rectClass = [Rectangle class];
    如同上面的例子显示的那样,类对象像其他对象一样,也是id类型。

    总之,类对象是一个功能完整的对象,所以也能被动态识别(dynamically typed),接收消息,从其他类继承方法。特殊之处在于它们是由编译器创建的,缺少它们自己的数据结构(实例变量),只是在运行时产生实例的代理。

    3、元类对象(metaclass object)
    ①元类对象的实质
    实际上,类对象是元类对象的一个实例!!元类描述了 一个类对象,就像类对象描述了普通对象一样。不同的是元类的方法列表是类方法的集合,由类对象的选择器来响应。当向一个类发送消息时,objc_msgSend会通过类对象的isa指针定位到元类,并检查元类的方法列表(包括父类)来决定调用哪个方法。元类代替了类对象描述了类方法,就像类对象代替了实例对象描述了实例化方法。
    很显然,元类也是对象,也应该是其他类的实例,实际上元类是根元类(root class’s metaclass)的实例,而根元类是其自身的实例,即根元类的isa指针指向自身。
    类的super_class指向其父类,而元类的super_class则指向父类的元类。元类的super class链与类的super class链平行,所以类方法的继承与实例方法的继承也是并行的。而根元类(root class’s metaclass)的super_class指向根类(root class),这样,整个指针链就链接起来了!!

    记住,当一个消息发送给任何一个对象, 方法的检查 从对象的 isa 指针开始,然后是父类。实例方法在类中定义, 类方法 在元类和根类中定义。(根类的元类就是根类自己)。在一些计算机语言的原理中,一个类和元类层次结构可以更自由的组成,更深元类链和从单一的元类继承的更多的实例化的类。Objective-C 的类方法 是使用元类的根本原因,在其他方面试图在隐藏元类。例如 [NSObject class] 完全相等于 [NSObject self],所以,在形式上他还是返回的 NSObject->isa 指向的元类。 Objective-C语言是一组实用的折中方案。

    还有些不明白? 下面这个图标可能会有些帮助:



    综上所述,类对象(class object)中包含了类的实例变量,实例方法的定义,而元类对象(metaclass object)中包括了类的类方法(也就是C++中的静态方法)的定义。类对象和元类对象中当然还会包含一些其它的东西,苹果以后也可能添加其它的内容,但对于我们只需要记住:类对象存的是关于实例对象的信息(变量,实例方法等),而元类对象(metaclass object)中存储的是关于类的信息(类的版本,名字,类方法等)。要注意的是,类对象(class object)和元类对象(metaclass object)的定义都是objc_class结构,其不同仅仅是在用途上,比如其中的方法列表在类对象(instance object)中保存的是实例方法(instance method),而在元类对象(metaclass object)中则保存的是类方法(class method)。关于元类对象可以参考苹果官方文档" The Objective-‐C Programming Language "

    4、类对象和元类对象的相关方法

    ①object_getClass跟随实例的isa指针,返回此实例所属的类,对于实例对象(instance)返回的是类(class),对于类(class)则返回的是元类(metaclass),
    ②-class方法对于实例对象(instance)会返回类(class),但对于类(class)则不会返回元类(metaclass),而只会返回类本身,即[@"instance" class]返回的是__NSCFConstantString,而[NSString class]返回的是NSString。
    ③class_isMetaClass可判断某类是否为元类.                                     

    ④使用objc_allocateClassPair可在运行时创建新的类与元类对,使用class_addMethod和class_addIvar可向类中增加方法和实例变量,最后使用objc_registerClassPair注册后,就可以使用此类了。看到动态语言牛逼的地方了吗,可以在需要时更改已经定义好的类!Objective-C的类别方法估计底层就是这么实现的,只是不知道为什么类别不能增加实例变量,有高手请留言。

    ----by wangzz


    展开全文
  •  前段时间公司的WebService接口需要处理xml数据,主要就是和对象之间的互相转换,传输的时候用xml,后台使用的时候转换成对象,所以就有了xmlobject之间经常的互相转换。  因为我们的项目使用的JDK是1.5,所以...

                   simple-xml2object组件禁止用于商业用途,作者:左潇龙。

                   前段时间公司的WebService接口需要处理xml数据,主要就是和对象之间的互相转换,传输的时候用xml,后台使用的时候转换成对象,所以就有了xml和object之间经常的互相转换。

                    因为我们的项目使用的JDK是1.5,所以并没有JAXB,如果要使用的话需要加入JAXB相关的jar包,但是感觉有点过大,而且使用起来有很多限制,而这些限制对我们的项目来说,毫无意义。比如在解析XML时,必须含有相关的命名空间,这使得我不得不在解析之前加入命名空间,因为WEBSERVICE的服务端并没有帮我们加入命名空间。

                    所以自己基于DOM开发了一个简易组件,可以实现xml和object的互相转换,功能简单实用,带有中文异常处理,虽说没英文显得专业,但感觉中文更实用,其中提示了所有异常产生最有可能的原因,还附带纯中文CHM文档,并保留了扩展性,有兴趣的也可以自己实现自己的转换机制。

                    由于引入了注解和泛型,所以需要JDK在1.5以上,另外如果你项目的JDK是1.6甚至1.7(估计1.7的不多),那就不再需要simple-xml2object了,因为JAXB已经被带入JDK,再使用就失去了simple-xml2object的意义,所以简单点说simple-xml2object适用于项目JDK版本为1.5的

                    在此分享给各位,如果有同样需求的,可以考虑,jar包大小26KB,因为全部基于JDK自带的类库,所以无需其余依赖包。

                    另外如果哪位在使用过程中有发现bug或者其他问题,可以在此留言,或者发我邮箱150349407@qq.com,我会及时更改。

                    目前最初始的版本1.0.0主要支持的功能有:

                    1.xml转换成object,并且可扩展实现自己的解析器,另外目前还不支持直接转换成一个对象的list,但是可以重复调用解析方法,同样可以产生一个list,有时间的话,下一版本会考虑直接支持此功能。

                    2.object转换成xml,支持xml格式的配置,包含无格式,只带换行的格式以及标准格式(也就是格式化以后的样子)。

                    3.日期格式采用注解方式,可直接在属性上面设置日期格式。

                    4.考虑到我们平时项目中对象的一个序列属性大部分是list或者是set的,所以此版本只支持属性为list或者set的,相信足够了。

                    jar包和CHM文档我已经打包,在我的资源里面可以免费下载,地址:http://download.csdn.net/detail/zuoxiaolong8810/5161785

                    下面是我专门为此组件写的一个测试类,用法简单明了,有详细的注释。

    import java.io.ByteArrayInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    import com.xml2object.simple.annotation.ADate;
    import com.xml2object.simple.container.ConfigurableContainer;
    import com.xml2object.simple.container.Container;
    import com.xml2object.simple.processor.XmlBulider;
    import com.xml2object.simple.processor.XmlBulider.Format;
    import com.xml2object.simple.support.DefaultConfigurableContainer;
    
    
    public class Test {
    	
    	String stringParam = "stringValue";
    	
    	@ADate(format = "yyyy-MM-dd hh")//日期注解,设置日期格式
    	Date dateParam = new Date();
    	
    	Test testParam;
    	
    	List<Test> testListParam;
    
    	public static void main(String[] args) throws IOException {
    		//不可配置的容器
    		Container container = new DefaultConfigurableContainer(Test.class);
    		//向容器中添加一个复杂的Test对象
    		container.add(createTest());
    		//获取容器自动解析的xml内容
    		String xml = container.getXml();
    		//将xml内容存放在一个文件中
    		write("E:/test1.xml", xml);
    		//可配置的容器,使用可配置的容器接口,推荐此种方式,比较灵活
    		ConfigurableContainer configurableContainer = new DefaultConfigurableContainer(Test.class);
    		XmlBulider xmlBulider = configurableContainer.getXmlBulider();
    		//设置构建器的xml格式
    		xmlBulider.setFormat(Format.TAB_AND_LINE);
    		//改变容器中的构建器
    		configurableContainer.setXmlBulider(xmlBulider);
    		//向可配置容器添加复杂对象
    		configurableContainer.add(createTest());
    		//获取容器自动解析的xml内容,比较下不能配置的容器构建的xml格式和日期格式
    		String configXml = configurableContainer.getXml(0);//等同于getXml()
    		//将xml内容存放在一个文件中
    		write("E:/test2.xml", configXml);
    		//再将xml从test2.xml中读取出来
    		String readableConfigXml = read("E:/test2.xml");
    		//向容器中再加入一个xml
    		configurableContainer.add(readableConfigXml);
    		//获取容器自动解析的对象
    		//因为之前已经加入了一个对象,所以在加入xml之前,容器中已包含一对xml和object,此时索引为1
    		//容器维护了两个保持一致的数组,分别存放xml和object,索引规则与数组一致,从0开始
    		Test test = configurableContainer.getObject(1);
    		//打印容器大小
    		System.out.println("size:" + configurableContainer.size());
    		//打印解析的对象,打印的可能不太清楚
    		//要想打印格式清晰,与我当初构建xml时相似,过程比较复杂,就不写那么详细了,各位可以自己加断点看对象内容
    		System.out.println(test);
    	}
    	
    	public static Test createTest(){
    		//构造一个复杂的Test,没什么特别的,复杂就好。。。
    		Test t = new Test();
    		Test t1 = new Test();
    		Test t2 = new Test();
    		Test t3 = new Test();
    		Test t4 = new Test();
    		Test t5 = new Test();
    		Test t6 = new Test();
    		Test t7 = new Test();
    		Test t8 = new Test();
    		Test t9 = new Test();
    		Test t10 = new Test();
    		List<Test> testList2 = new ArrayList<Test>();
    		testList2.add(t1);
    		testList2.add(t2);
    		List<Test> testList = new ArrayList<Test>();
    		t10.testListParam = testList2;
    		testList.add(t10);
    		testList.add(t9);
    		testList.add(t8);
    		testList.add(t7);
    		testList.add(t6);
    		t5.testListParam = testList;
    		t5.testParam = t4;
    		t3.testParam = t5;
    		t.testParam = t3;
    		return t;
    	}
    	
    	public String toString(){
    		StringBuffer stringBuffer = new StringBuffer();
    		stringBuffer.append("stringParam:" + (stringParam == null? "" : stringParam) + "\r\n")
    		.append("dateParam:" + (dateParam == null ? "" : dateParam) + "\r\n")
    		.append("testParam:" + (testParam == null ? "" : testParam) + "\r\n");
    		if (testListParam != null) {
    			stringBuffer.append("testListParam:\r\n");
    			for (Test temp : testListParam) {
    				stringBuffer.append(temp + "\r\n");
    			}
    		}
    		return stringBuffer.toString();
    	}
    	
    	public static String read(String fileName) throws IOException{
    		File file = new File(fileName);
    		FileInputStream fileInputStream = new FileInputStream(file);
    		byte[] bytes = new byte[(int) file.length()];
    		fileInputStream.read(bytes);
    		return new String(bytes);
    	}
    	
    	public static void write(String fileName,String xml) throws IOException{
    		OutputStream outputStream = new FileOutputStream(new File(fileName));
    		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xml.getBytes());
    		int len = -1;
    		byte[] bytes = new byte[1024];
    		while ((len = byteArrayInputStream.read(bytes)) != -1) {
    			outputStream.write(bytes, 0, len);
    		}
    		outputStream.flush();
    		outputStream.close();
    		byteArrayInputStream.close();
    	}
    	
    }
    

                     新建一个java工程,将下载的jar包导入,再直接将测试类代码贴到一个java文件中,运行即可得到E盘下两个xml,可以看下我们配置的日期格式注解是否有效,另外两个xml,一个是不可配置的容器生成的,一个是我们采用可配置容器,调整格式后生成的,可以比对下其中的xml格式,是不是test2已经被格式化了呢?

                     xml格式化功能一般只是用于测试的时候使用,其主要意义是为了方便测试,因为在测试的时候,我们经常会把生成的xml打印到控制台,控制台不像编辑器可以格式化,所以这样的话看起来效果很差。当然,如果你不嫌麻烦,也可以写入一个文件,然后用编辑器打开手动格式化。

                     至于只换行的功能,一般在层级太多的时候使用,这个我想道理很简单,层次太多,打印出来的xml横向宽度会很长,也不便于观察。但是只换行的话如果层次太多其实也不太便于观察,所以从这个角度来看,这个格式貌似有些鸡肋,但我觉得完全格式化与空格式总要有个过渡,保证程序的完整性,所以就加进去了。

                     在数据传输过程中,建议使用无格式,节省传输流量。

    展开全文
  • 从PHP函数参数为数组和对象的区别说开去 ...函数参数为数组和对象的区别 变量的底层结构 对象的底层结构 *HashTable —PHP的灵魂 函数参数为数组和对象的区别 先写一个不算很好的例子但是足够说明问题了。...

    从PHP函数参数为数组和对象的区别说开去

    从PHP函数形式参数为数组和对象的区别说开去,首先比较一下函数的参数为数组和对象的区别,然后由此说开,谈谈变量的底层结构,对象的底层结构,hashTable的底层结构。

    • 函数参数为数组和对象的区别
    • 变量的底层结构
    • 对象的底层结构
    • *HashTable —PHP的灵魂

    这里写图片描述

    函数参数为数组和对象的区别

    先写一个不算很好的例子但是足够说明问题了。

    这里写图片描述

    class Test {
       public $b = 0;
    
    }
    
    function change( $a   )
    {
        if(is_array($a)  ){
    
           $a['a'] = 1;
        }else{
           $a->b= 1;
        }
        return $a ;
    }
    
    $array = [ 1, 2, 3,'a'=>2];
    $b = new  Test();
    var_dump(($array));
    echo 'up array dowm class ';
    var_dump(($b));
    echo 'no cchange  ';
    change($array);
    var_dump($array);
    echo 'up array dowm class ';
    change($b);
    var_dump(($b));
    
    

    打印结果如下:

    array(4) {
     [0]=>
     int(1)
     [1]=>
     int(2)
     [2]=>
     int(3)
     ["a"]=>
     int(2)
    }
    up array dowm class object(Test)#1 (1) {
     ["b"]=>
     int(0)
    }
    no cchange  array(4) {
     [0]=>
     int(1)
     [1]=>
     int(2)
     [2]=>
     int(3)
     ["a"]=>
     int(2)
    }
    up array dowm class object(Test)#1 (1) {
     ["b"]=>
     int(1)
    }

    数组在函数中被改变了,但是并不影响原本的数组,这说明数组的传递是一个值传递(副本),而对象的传递是引用传递所以函数中改变了对象的属性,所以原本的对象也被改变了。而且据说“因为php内置函数默认就是传的值而不是引用”。笔者目前没有看见任何资料上有这句话,又看到的朋友欢迎留言指证。很明显上面的例子说明了问题,不管对象的传递默认是传值还是传引用对对象来说都变了。

    点击链接进入页面可以看到:“因为php内置函数默认就是传的值而不是引用”。 在array_map函数讲解那块!!!—— 重剑无锋 大巧不工

    变量有作用的存在就没有这个问题了,这里不再赘述。

    变量的底层结构

    都知道PHP内核是C写的。
    下面根据PHP变量的结构开始介绍一系列PHP底层的C代码。
    变量是PHP的源泉。笔者认为的!!!

    因为数组是一种变量,而对象也是一种变量。—— PHP核心技术与最佳实践第四页

    变量的结构C代码如下:

    typedef struct _zvalue_value{
    long lval;// 存放long、bool和resource
    double dval;
    struct {
        char *val;
        int len;
    }str;
     HashTable   * ht;// 本文后面会讲
     zend_object_value obj;
    
    }zvalue_value;

    值得注意的是所有变量的底层类型都是zvalue_value。
    看到这里大家似乎有点理解为什么PHP中变量可以存储各种类型了。
    别急,变量还需要一个结构去存储引用等信息,也就是有名的zval结构体。

    struct _zval_struct{
    zvalue_value val;// 存放PHP变量的值
    zend_uint refcount; // 变量引用计数
    zend_uchar is_ref; // 变量是否被引用
    zend_uchar type; // 变量的类型
    }zval_struct;
    
    typedef _zval_struct zval;

    结构体重的type的取值如下表

    PHP类型
    IS_NULL0NULL
    IS_LONG1整数
    IS_DOUBLE2浮点
    IS_STRING3字符串
    IS_ARRAY4数组
    IS_OBJECT5对象
    IS_BOOL6布尔
    IS_RESOURCE7资源(句柄)

    这里写图片描述

    zval结构体是PHP变量在内核中表示方式。—— PHP核心技术与最佳实践第260页

    
     $a = 1;
    $b = '0';
    var_dump($a);
    var_dump($b);
    $a = $b ; 
    var_dump($a);
    
    $a = (int) $b ; 
    var_dump($a);
    

    打印如下:

    int(1)
    string(1) "0"
    string(1) "0"
    int(0)
    

    PHP变量有一个节省内存的方案:写时复制

    也就是在变量赋值给另一个变量时并不会马上分配一个新的内存块,而是当这2个变量不一样时(其中有人变化了),才会重新分配一块内存去单独存放(内存的复制)。

    //比如 
    $a =2;
    $a = $b;
    // 此时$a$b相同,都指向一块相同的内存块,没有分配一个多余的内存块去
    // 单独存放$a或者$b,下面改变$b
    $b = 1;// 此时发现$b变化了,在分配一块内存去存放$b

    对象的底层结构

    对象的底层由属性数组和方法数组共同组成。
    这里写图片描述

    对象在zend引擎中的定义如下:

    typedef struct _zend_object {
    zend_class_entry *ce; // 类指针
    HashTable  * properties;// 对象的属性
    HashTable * guards; // 阻止递归调用
    }zend_object;

    值得注意的是,根据_zend_object结构体可以看到对象的属性和类指针是2个指针,也就是说一个类的对象和它的属性是分开了。
    怎么说?解释一下:加入$a 是类test的对象,那么ce指针指向test类,也就是test类有的对象a都有,而对象特有的(比如动态创建的成员属性或者方法)在properties指针中,而不在ce指针中,这就导致了说为什么PHP对象可以动态创建成员。

    class tests {
    
        public $a = '123';
    
    } 
    echo "class";
    $a = new tests();
    var_dump(new tests());
    var_dump($a);
    $a->b = 'abf';
    echo "class";
    var_dump(new tests());
    var_dump($a);
    
    

    打印如下:

    classobject(tests)#2 (1) {
     ["a"]=>
     string(3) "123"
    }
    object(tests)#1 (1) {
     ["a"]=>
     string(3) "123"
    }
    classobject(tests)#2 (1) {
     ["a"]=>
     string(3) "123"
    }
    object(tests)#1 (2) {
     ["a"]=>
     string(3) "123"
     ["b"]=>
     string(3) "abf"
    }
    
    

    这个例子完美的证明了,当给对象动态创建成员属性时,并不影响类。当再次实例化类时,新的对象并没有以前对象动态创建的属性。精髓就在指针properties上。
    指针ce也是对象与数组的区别的显著特征。对象有一个指向所属类的指针,而数组没有。

    HashTable —PHP的灵魂

    HashTable由HashTable和Bucket组成。为了不弄混,也为了不让读者蒙圈笔者尽量换个角度解释HashTable,尽量浅显易懂一点。

    这里写图片描述

    HashTable数据结构由2部分组成,它本身和外部的一个叫Bucket的结构体。
    先看完整的HashTable结构体定义。

    typedef  struct _hashtable {
    uint nTableSize;// 记录Bucket数组的大小
    uint nTableMask; // 等于nTableSize-1
    uint nNumberOfElements;// 记录HashTable中元素的个数
    ulong nNextFreeElement;// 下一个可用Bucket位置
    Bucket * pInternalPointer;// 遍历HashTable元素
    Bucket * pListHead;// 双链表表头
    Bucket * pListTail;// 双链表表尾
    Bucket * * arBuckets;// Bucket数组
    dtor_func_t pDestructor;// pDestructor
    zend_bool persistent;// persistent,是否使用PHP的内存管理默认是否则使用操作系统
    unsigned char nApplyCount;// 0
    zend_bool bApplyProtection;// 1
    }HashTable;
    
    // Bucket
    typedef struct  bucket{
    ulong h;// hash之后的hash值
    uint  nKeyLength;// 索引的长度
    void  *pData;// 保存的内存块地址
    void  *pDataPtr;// 指针数据
    struct  bucket *pListNext; // 指向双向链表的下一个元素 
    struct  bucket *pListLast;// 指向双向链表的上一个元素
    struct  bucket *pNext;// 指向相同hash值的下一个元素--拉链法
    struct  bucket *pLast;// 指向相同hash值的上一个元素--拉链法
    char    arKey[1]; // 保存索引,而且必须是最后一个成员???
    }Bucket;
    

    这里说明以下几点:
    1 hashtable之所以维护双向链表是为了有序遍历hashtable中的元素;
    2 nTableSize的大小不是PHP实际申请的内存的大小,PHP申请的内存大小是不小于nSize的2的n次方。比如要求申请7 那么 申请的大小是 2^n = 8>=7;
    3 最好使用PHP的内存管理,操作系统去管理内存容易造成内存泄漏,persistent设置为true;

    下面分析hashtable的插入过程:
    1 申请内存(Bucket结构体保存索引和值);
    2 索引复制到arkey中;
    3 pData指向值;
    4 把新Bucket添加具有相同hash值的双向链表中,没有就是该双向链表的第一个元素(主要通过宏 CONNECT_TO_BUCKET_DLLIST完成);
    5 把新Bucket添加到Hashtable双向链表中(通过CONNECT_TO_GLOBAL_DLLIST宏完成);
    6 插入完成后,进行统计,如果HashTable元素的个数大于arBuckets数组的大小(nNumOfElements大于nTableSize),将hashtable的arBuckets数组大小翻倍,始终保持nNumOfElements小于nTableSize。

    以上是个人总结和读书笔记整理而来,有些地方可能有笔误望指正!!!
    这里写图片描述

    留个随堂练习:请问hashtable中有几个双向链表?

    展开全文
  • JVM系列之:对象的锁状态同步

    万次阅读 2020-07-24 09:14:07
    同步是java多线程编程中非常常见的使用场景。为了锁定多线程共享的对象,Java需要提供一定的机制来实现共享对象的锁定,从而保证一次只有一个线程能够作用于共享对象。当第二个线程进入同一个区域的时候,必须...
  • js中的面向对象语法编程思想

    千次阅读 2018-03-23 11:23:46
    @昨晚朋友聊了很久的编程思想;她跟我说:自己之前是一些CSSHTML为主,对js涉猎的比较少,... 那么咱们下面就说说面向对象和原型链的问题。一、面向对象 ECMAScript有两种的开发模式:1、函数化(过程式),2...
  • 在类上加@Component或者其他注解时,该类会交给spring来管理,自动创建对象,但是如果是自己new出来的对象或者自己类没加注解,但是内部又需要注入其他对象以及需要注入配置文件中的属性时,有以下办法解决: ...
  • 对象的构成模型关系模型

    千次阅读 2012-09-22 16:17:52
    1.对象的构成模型  作为面向对象编程最基本的构成元素,对象是由一个叫做类(Class)的概念来描述的。因此,针对对象构成分析的研究,也就转化为针对编程语言中类的构成分析。以Java语言为例,我们可以对Java语言中...
  • 面向对象的开发,终究是要有个对象,不能老是玩函数。
  • C++对象对象数组的排序

    千次阅读 多人点赞 2015-06-24 12:20:35
    C++对象对象数组的排序
  • JQuery对象与js对象的相互转换

    万次阅读 2021-02-23 00:13:12
    JQuery对象和JS对象区别与转换 1. JQuery对象在操作时,更加方便。 2. JQuery对象和js对象方法不通用的。 3. 两者相互转换。 * jq -- > js : jq对象[索引] 或 jq对象.get(索引) * js -- > jq : $(js...
  • 学习open62541 --- [7] Server添加对象和对象类型

    千次阅读 多人点赞 2019-09-27 22:45:29
    显示如下, 在Reference窗口中可以看到对象节点变量节点之间的关系,即HasComponent 二 自定义对象类型 上一节我们手动添加了一个学生对象节点,可以看出来需要写很多代码,如果有100个学生对象,那么代码量就很大...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 112,625
精华内容 45,050
关键字:

和对象分别的留言