黑马程序员技术交流社区

标题: Java创建对象的四种方式 [打印本页]

作者: Tking    时间: 2014-4-11 03:30
标题: Java创建对象的四种方式

Java创建对象的四种方式

第一种:使用new关键字创建对象,最为普遍的方式。

第二种:反射机制,载入类的字节码,然后拿到构造方法建立对象,或者用字节码建立无参对象。(前提是该类要有无参构造方法)
第三种:克隆机制,让某一类实现Cloneable接口,重写clone方法,在调用该方法,可以生成一个克隆对象。
第四种:运用反序列化手段,条用Java.io.ObjectInputStream对象的readObject()写入一个对象。(这个方式还在研究中,所以就不写了)
下面几种方式,用一个单例模式来表现出每种方法的优点和缺点。
单例模式:该类在内存中只会存在一个对象。
  1. class A{  
  2.     public String name="name";  
  3.     private A(){}
  4.     private static A a=new A();
  5.     public static A getA()
  6.     {
  7.             return a;
  8.       }
复制代码
1.使用new关键字创建对象。
  1. 示范:Object obj=new Object();
  2. A a1=A.getA();//对于单例只能用提供的静态方法获取对象。
复制代码
就这么简单,一个对象就建立成功了。
2.反射机制,可以避过单例的私有化,从而创建该单例的第二个对象。
示范:
  1. Constructor con;
  2. (con=a1.getClass().getDeclaredConstructor(null)).setAccessible(true;
  3. A a2=(A)con.newInstance(null);
复制代码
3.克隆机制,让某个类实现Cloneable,该类的对象便可以使用clone()方法实施克隆,同一个字节码,不同的对象。同时这种方法也可以克服java的指针的概念,达到理论上真正的copy
示范:
  1. class A implements Cloneable {  //实施克隆机制必须实现Cloneable接口
  2.     public String name="name";  
  3.     private A(){}
  4.     private static A a=new A();
  5.     public static A getA()
  6.     {
  7.             return a;
  8.     }
  9.     public Object clone() throws CloneNotSupportedException{//并重写clone()
  10.         return super.clone();  
  11.     }  
  12.   }  
  13. Class Demo
  14. Public static void main(String[] args)
  15. {
  16.   A a1=A.getA();
  17.   a1.name="a1";
  18.   A a4=a1;
  19.   System.out.println("a1-name"+a1.name);
  20.   System.out.println("a4-name"+a4.name);
  21.   
  22.   a4.name="a4";
  23.   System.out.println("a1-name"+a1.name);
  24.   System.out.println("a4-name"+a4.name);
  25. }
  26. //打印结果:
  27.   a1.name=a1
  28.   a4.name=a1

  29.   a1.name=a4
  30.   a4.name=a4
复制代码
这样的=赋值只是将a1的地址给了a4,两个变量指向同个对象,a4在修改其内部属性时,a1也会受到影响,这种方式不是我们想得到,这里就要用到clone
  1.   a1.name="a1";
  2.   A a3=(A)a1.clone();
  3.   System.out.println("a1-name"+a1.name);
  4.   System.out.println("a3-name"+a3.name);
  5.   
  6.   a3.name="a3";
  7.   System.out.println("a1-name"+a1.name);
  8.   System.out.println("a3-name"+a3.name);
  9. //打印结果:
  10.   a1.name=a1
  11.   a3.name=a1
  12.   
  13.   a1.name=a1
  14.   a3.name=a3
复制代码
使用clone()后,达到了正真意义上的赋值,将整个对象都拷贝,修改任意对象都不会对对方的属性有影响。
综合演示:
  1.   Class Demo
  2.   Public static void main(String[] args)
  3.   {
  4.     Constructor con;
  5.     A a1=A.getA();//以下操作都基于a1进行
  6.   a1.name="a1";
  7.          (con=a1.getClass().getDeclaredConstructor(null)).setAccessible(true;
  8.     A a2=(A)con.newInstance(null);
  9.     A a3=a1.clone();
  10.   A a4=a1;
  11.   System.out.println("a1-name"+a1.name);
  12.     System.out.println("a2-name"+a2.name);
  13.     System.out.println("a3-name"+a3.name);
  14.   System.out.println("a4-name"+a4.name);
  15.   
  16.     a1.name="a1";
  17.     a2.name="a2"
  18.     a3.name="a3";
  19.   a4.name="a4";
  20.     System.out.println("a1-name"+a1.name);
  21.     System.out.println("a2-name"+a2.name);
  22.     System.out.println("a3-name"+a3.name);
  23.   System.out.println("a4-name"+a4.name);
  24.   }
复制代码
从前四排结果可以看出,反射是新建了一个对象,而其余的都是很像是指向了同一个对象。
从后四排的结果就明白了,clone()是完全克隆出一个相同对象,拥有母体的相同属性与方法,但是与母体没有指针的关系,而“=”则是将地址赋值给某个变量。
总结:
当需要多引用指向同一个对象时,可以使用“=”,能达到一处修改,多处改变。
当需要拷贝一个完全相同的对象,并且修改属性,不影响到源对象时,应该用clone
反射只能创建出一个字节码的新实例对象,不能达到拷贝的效果。
而反序列化,是将某些对象与对象现在状态存储到文件中,之后可以用IO的形式将该对象读取出来,可以达到存取的功能。(没实践过,只看了帮助文档,用起来也挺复杂,没做演示)




作者: Tking    时间: 2014-4-11 10:22
怎么不支持下呢?好没动力




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2