最近面试,有一道题考的是java的对象是否必须通过构造方法生成。当时可能是脑子进水了,像C里面可以直接内存拷贝,然后用指针引用就可以视为生成了一个新对象,java虽然不提供这种危险的方式,但是肯定也有类似方式,所以答案肯定是是否然的。那么就列一下以下几种对象生成方式,如果后面有其他方式那么后续补充。
public class Tclass implementsSerializable,Cloneable {/****/
private static final long serialVersionUID = -2146400774304662925L;
Tclass(){
System.out.println("Tclass constructor invoked");
}
@OverridepublicTclass clone(){try{return (Tclass)super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();return null;
}
}
}
上面是测试的类,顺便记下,之前将Tclass这个类作为内部类 来用,发现就算实现了Serializable接口序列化还是会报错,可能跟外部类挂钩,这里先不多说注意一下即可。
下面是测试几种生成对象的方法的代码:
@Testpublic voidtestGetObject(){
System.out.println("start generate test1---------------");
Tclass test1=newTclass();
System.out.println("end generate test1---------------");
System.out.println("start generate test2---------------");
Tclass test2=test1.clone();
System.out.println("end generate test2---------------");
Tclass test3=null;
Tclass test4=null;try(ByteArrayOutputStream os=newByteArrayOutputStream();
ObjectOutputStream oos=newObjectOutputStream(os);
) {
oos.writeObject(test1);byte[] results=os.toByteArray();try(ObjectInputStream ois=new ObjectInputStream(newByteArrayInputStream(results));) {
System.out.println("start generate test3---------------");
test3=(Tclass)ois.readObject();
System.out.println("end generate test3---------------");
}catch(ClassNotFoundException e) {//TODO Auto-generated catch block
e.printStackTrace();
}
}catch(IOException e) {//TODO Auto-generated catch block
e.printStackTrace();
}try{
System.out.println("start generate test4---------------");
test4=(Tclass) Class.forName("lm.Tclass").newInstance();
System.out.println("end generate test4---------------");
}catch(InstantiationException e1) {//TODO Auto-generated catch block
e1.printStackTrace();
}catch(IllegalAccessException e1) {//TODO Auto-generated catch block
e1.printStackTrace();
}catch(ClassNotFoundException e1) {//TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("test1 is :"+test1);
System.out.println("test2 is :"+test2);
System.out.println("test3 is :"+test3);
System.out.println("test4 is :"+test4);
}
最终打印结果为:
start generate test1---------------
Tclass constructor invoked
end generate test1---------------
start generate test2---------------
end generate test2---------------
start generate test3---------------
end generate test3---------------
start generate test4---------------
Tclass constructor invoked
end generate test4---------------
test1 is :lm.Tclass@20d547f8
test2 is :lm.Tclass@22067303
test3 is :lm.Tclass@5568db68
test4 is :lm.Tclass@571cb4a6
可以看出,test1和test4使用new 和 反射方式调用,实际上都是调用构造方法生成对象的方式。而通过clone和反序列化生成对象是不调用构造方法的。