本文主要介绍java创建对象的方法,闲话少叙。
Java创建对象的方法有多种,常见基本如下:
1、用new语句创建对象,这是最常见的创建对象的方法。
2、通过工厂方法返回对象,如:String str = String.valueOf(23);
3、运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
Object obj = Class.forName("java.lang.Object").newInstance();
4、调用对象的clone()方法。实现Cloneable接口,然后重写Object.clone()方法创建对象.
5、通过I/O流(包括反序列化),如运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。
6、String str="abc" 直接由jvm创建 或者使用 字符串操作符"+" String str1 = "a"+"bc"由jvm创建。
创建对象方法比较:
new:
1.JVM首先检查该类是否加载,没有加载会先加载类,对类进行加载,解析和初始化;
2.加载类后,JVM对该对象在Java堆中分配内存,
3.设置对象,先对对象的初始化零值,就是对象字段初始化为零值;再对对象的对象头部分初始化,就是设置该对象的JVM相关属性,比如该对象属于哪个类,hash值,GC年代等。至此,从JVM看,对象创建了。
4.执行<init>方法,按照程序员的意愿对对象的各个属性设置。比如,设置各个域的初始值。
clone:
clone目的是复制一个原对象的copy,简单的就是内存复制,所以简单的clone是很快的,即与原对象相同,但是不一样,对新对象的操作不会影响原对象。clone在java规范中要求 1. a.clone() != a; 2. a.clone().getClass = a.getClass(); 3. a.clone().equals(a).
clone要求对象实现clonable接口,Object的clone方法会检测对象是够实现了这个接口。Object方法的clone方法是protected,即只有子类和同包(自定义类自然做不到和Object同包)才能调用。
clone分浅clone和深clone。
浅clone,Shallow Clone,就是逐域拷贝,默认实现cloneable接口或者简单覆盖clone方法就是浅clone。例如:
public class A implements Cloneable {
public String name;
public Object clone() {
A o = null;
try {
o = (A) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
}
一个类如果只有基本类型和字符串这样的不可变对象,那么仅仅实现Cloneable就够了。但是如果类中包含数组或者复杂对象,就需要深clone,即正确生成新对象。例如:
public class A implements Cloneable {
public String name[];
public Vector<B> claB;
public A(){
name=new String[2];
claB=new Vector<B>();
}
public Object clone() {
A o = null;
try {
o = (A) super.clone();
o.name==(String[])name.clone();//深度clone
o.claB=new Vector<B>();//将clone进行到底
for(int i=0;i<claB.size();i++){
B temp=(B)claB.get(i).clone();//当然Class B也要实现相应clone方法
o.claB.add(temp);
}
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return o;
}
}
其实,clone方法分三种情况处理。
1.对象只包含基本类型的域或者域指向了一个不可变对象,这种情况只需实现cloneable接口即可。
2.域中包含数组的对象,只需调用数组的clone方法。
3.域包含可变对象。这就是需要我们特别关照的情况,我们必须将这些可变的部分手动。比如,List。
下面有例子(有些正确clone,有些没有):
package basic.objects.methods;
import java.util.ArrayList;
import java.util.List;
/**
* 检测数组的clone的正确定。 c2的改变不应该引起c1对象的改变,这是clone的意义。
*/
public class Clones implements Cloneable {
int[] ints;// 没有正确clone
double[] doubles;// 正确处理
List<String> strs;// 没有正确处理
List<Character> chs; // 正确处理
public Clones() {
ints = new int[] { 0 };
doubles = new double[] { 0 };
strs = new ArrayList<String>();
chs = new ArrayList<Character>();
}
@Override
public Clones clone() {
try {
Clones c = (Clones) super.clone();
c.doubles = doubles.clone();
c.chs = new ArrayList<Character>(chs);
return c;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) throws CloneNotSupportedException {
Clones c1 = new Clones();
Clones c2 = (Clones) c1.clone();
c2.ints[0] = 1;
c2.doubles[0] = 1;
c2.strs.add("new str in c2 added");
c2.chs.add('H');
System.out.println(c1.ints[0]);
System.out.println(c1.doubles[0]);
System.out.println(c1.strs);
System.out.println(c1.chs);
}
}
反射:
反序列化往往是对于类在remote或者是一串特殊文本等的情况。简单说,Java自带的反序列化就是读取字节流,然后通过反射调用class的newInstance()方法,构造出新对象。反射构造对象具体见 这里 。
下面是关于创建速度的文章,有兴趣可以一看。http://my.oschina.net/u/1428349/blog/299205