首先,博主最近读《Java编程思想》有感,总结了记住创建对象得方式,并分别列举了他们之间得关系和区别,希望对大家面向对象得思想有所启发。
博主总结Java中有5种创建对象的方式,下面给出它们的例子还有它们的测试代码:
首先,列举这5种创建对象得方式:
使用得方法 | 是否调用构造函数 |
---|---|
使用New关键字 | 是 |
使用Class类的newInstance | 是 |
使用Constructor类的newInstance方法 | 是 |
使用clone方法 | 否 |
使用反序列化得方法 | 否 |
说到这个关键字,我想大家再熟悉不过了把,这是最常见也是最简单的创建对象的方式了。通过这种方式,我们可以调用任意的构造函数(无参的和带参数的)。
Woman girlfirend = new Woman();
哈哈,博主开个玩笑,给大家New了一个女朋友,好了言归正传,New关键字在创建对象的时候得流程是怎样得呢?
1.为新对象分配内存空间,将MyDate存储到堆。
2.执行显示的初始化
3.执行构造器。new方法中括号参数传递给构造器,出书话该对象数值
4.该变量被赋值为堆内存中新对象的引用
通俗的说,你new的操作,实际上是在内存的堆中新添加一个new的对象并且通过构造方法初始化这个新对象并且在栈中存放该对象的引用。
我们也可以使用Class类的newInstance方法创建对象。这个newInstance方法调用无参的构造函数创建对象。
我们可以通过下面方式调用newInstance方法创建对象:
Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee").newInstance();
或者
Employee emp = Employee.class.newInstance();
和Class类的newInstance方法很像, java.lang.reflect.Constructor类里也有一个newInstance方法可以创建对象。我们可以通过这个newInstance方法调用有参数的和私有的构造函数。
Constructor<Employee> constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();
上面两种创建对象得方法newInstance方法就是大家所说的反射。事实上Class的newInstance方法内部调用Constructor的newInstance方法。这也是众多框架,如Spring、Hibernate、Struts等使用后者的原因。
以下对两种调用方式给以比较说明:
Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数;
Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数。
Class.newInstance() 抛出所有由被调用构造函数抛出的异常。
Class.newInstance() 要求被调用的构造函数是可见的,也即必须是public类型的;
Constructor.newInstance() 在特定的情况下,可以调用私有的构造函数
无论何时我们调用一个对象的clone方法,jvm就会创建一个新的对象,将前面对象的内容全部拷贝进去。用clone方法创建对象并不会调用任何构造函数。
要使用clone方法,我们需要先实现Cloneable接口并实现其定义的clone方法。
Employee emp4 = (Employee) emp3.clone();
当我们序列化和反序列化一个对象,jvm会给我们创建一个单独的对象。在反序列化时,jvm创建对象并不会调用任何构造函数。
为了反序列化一个对象,我们需要让我们的类实现Serializable接口
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();
我们从上面的字节码片段可以看到,除了第1个方法,其他4个方法全都转变为invokevirtual(创建对象的直接方法),第一个方法转变为两个调用,new和invokespecial(构造函数调用)。
下面的Java程序中,我们将用5种方式创建Employee对象,你可以从GitHub找到这些代码。
public class ObjectCreation {
public static void main(String... args) throws Exception {
// By using new keyword
Employee emp1 = new Employee();
emp1.setName("fan");
System.out.println(emp1 + ", hashcode : " + emp1.hashCode());
// By using Class class's newInstance() method
Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee") .newInstance();
// Or we can simply do this
//Employee emp2 = Employee.class.newInstance();
emp2.setName("yin");
System.out.println(emp2 + ", hashcode : " + emp2.hashCode());
// By using Constructor class's newInstance() method
Constructor constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance(); emp3.setName("lee");
System.out.println(emp3 + ", hashcode : " + emp3.hashCode());
// By using clone() method
Employee emp4 = (Employee) emp3.clone();
emp4.setName("zhao");
System.out.println(emp4 + ", hashcode : " + emp4.hashCode());
// By using Deserialization
// Serialization
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.obj")); out.writeObject(emp4); out.close();
//Deserialization
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();
in.close();
emp5.setName("he");
System.out.println(emp5 + ", hashcode : " + emp5.hashCode());
}}
输出结果:
Employee Constructor Called...Employee [name=fan], hashcode : -1968815046
Employee Constructor Called...Employee [name=yin], hashcode : 78970652
Employee Constructor Called...Employee [name=lee], hashcode : -1641292792
Employee [name=zhao], hashcode : 2051657
Employee [name=he], hashcode : 63313419
java创建对象就这几种方式了,也算是我最近读《Java编程思想》这本书得总结,一直想写一篇这样得文章,使自己面向对象得思想更加清晰明了一些,最后,这次我们真的不止会New了,我们有了这么多方式,哈哈。