第二种:反射机制,载入类的字节码,然后拿到构造方法建立对象,或者用字节码建立无参对象。(前提是该类要有无参构造方法)
第三种:克隆机制,让某一类实现Cloneable接口,重写clone方法,在调用该方法,可以生成一个克隆对象。
第四种:运用反序列化手段,条用Java.io.ObjectInputStream对象的readObject()写入一个对象。(这个方式还在研究中,所以就不写了)
下面几种方式,用一个单例模式来表现出每种方法的优点和缺点。
单例模式:该类在内存中只会存在一个对象。
- class A{
- public String name="name";
- private A(){}
- private static A a=new A();
- public static A getA()
- {
- return a;
- }
复制代码1.使用new关键字创建对象。
- 示范:Object obj=new Object();
- A a1=A.getA();//对于单例只能用提供的静态方法获取对象。
复制代码就这么简单,一个对象就建立成功了。
2.反射机制,可以避过单例的私有化,从而创建该单例的第二个对象。
示范:
- Constructor con;
- (con=a1.getClass().getDeclaredConstructor(null)).setAccessible(true;
- A a2=(A)con.newInstance(null);
复制代码3.克隆机制,让某个类实现Cloneable,该类的对象便可以使用clone()方法实施克隆,同一个字节码,不同的对象。同时这种方法也可以克服java的指针的概念,达到理论上真正的copy。
示范:
- class A implements Cloneable { //实施克隆机制必须实现Cloneable接口
- public String name="name";
- private A(){}
- private static A a=new A();
- public static A getA()
- {
- return a;
- }
- public Object clone() throws CloneNotSupportedException{//并重写clone()
- return super.clone();
- }
- }
- Class Demo
- Public static void main(String[] args)
- {
- A a1=A.getA();
- a1.name="a1";
- A a4=a1;
- System.out.println("a1-name"+a1.name);
- System.out.println("a4-name"+a4.name);
-
- a4.name="a4";
- System.out.println("a1-name"+a1.name);
- System.out.println("a4-name"+a4.name);
- }
- //打印结果:
- a1.name=a1
- a4.name=a1
- a1.name=a4
- a4.name=a4
复制代码这样的=赋值只是将a1的地址给了a4,两个变量指向同个对象,a4在修改其内部属性时,a1也会受到影响,这种方式不是我们想得到,这里就要用到clone
- a1.name="a1";
- A a3=(A)a1.clone();
- System.out.println("a1-name"+a1.name);
- System.out.println("a3-name"+a3.name);
-
- a3.name="a3";
- System.out.println("a1-name"+a1.name);
- System.out.println("a3-name"+a3.name);
- //打印结果:
- a1.name=a1
- a3.name=a1
-
- a1.name=a1
- a3.name=a3
复制代码使用clone()后,达到了正真意义上的赋值,将整个对象都拷贝,修改任意对象都不会对对方的属性有影响。
综合演示:
- Class Demo
- Public static void main(String[] args)
- {
- Constructor con;
- A a1=A.getA();//以下操作都基于a1进行
- a1.name="a1";
- (con=a1.getClass().getDeclaredConstructor(null)).setAccessible(true;
- A a2=(A)con.newInstance(null);
- A a3=a1.clone();
- A a4=a1;
- System.out.println("a1-name"+a1.name);
- System.out.println("a2-name"+a2.name);
- System.out.println("a3-name"+a3.name);
- System.out.println("a4-name"+a4.name);
-
- a1.name="a1";
- a2.name="a2"
- a3.name="a3";
- a4.name="a4";
- System.out.println("a1-name"+a1.name);
- System.out.println("a2-name"+a2.name);
- System.out.println("a3-name"+a3.name);
- System.out.println("a4-name"+a4.name);
- }
复制代码从前四排结果可以看出,反射是新建了一个对象,而其余的都是很像是指向了同一个对象。
从后四排的结果就明白了,clone()是完全克隆出一个相同对象,拥有母体的相同属性与方法,但是与母体没有指针的关系,而“=”则是将地址赋值给某个变量。
总结:
当需要多引用指向同一个对象时,可以使用“=”,能达到一处修改,多处改变。
当需要拷贝一个完全相同的对象,并且修改属性,不影响到源对象时,应该用clone。
反射只能创建出一个字节码的新实例对象,不能达到拷贝的效果。
而反序列化,是将某些对象与对象现在状态存储到文件中,之后可以用IO的形式将该对象读取出来,可以达到存取的功能。(没实践过,只看了帮助文档,用起来也挺复杂,没做演示)