Java创建对象的四种方式

Java创建对象的方式从是否调用了构造函数可以分为两种

调用了构造函数

1)使用new关键字

2)使用Class类的newInstance方法:

a.使用Class类的forName方法

b.使用ClassLoader类的loadClass方法

3)使用Constructor类的newInstance方法

没有调用构造函数

1)使用clone方法

2)使用反序列化

Java创建对象的方式在使用技术上可以大体分为4种(个人理解,也可以分为5种等)

1.使用new关键字创建对象

 

这个是我们常用的创建对象的方式,通过new 类名()可以调用此类的构造函数(无参和有参)。这种方式,类的生命周期中的加载、初始化、实例化三个操作都会执行

Person  person = new Person();

2.使用反射创建对象

 

这三种newInstance方法就是大家所说的反射,可以归为一类。事实上Class的newInstance方法内部调用Constructor的newInstance方法。

我们也可以使用Class类的newInstance方法创建对象。这个newInstance方法调用无参的构造函数创建对象。

一)使用Class类的forName方法

Class c = Class.forName("类名"); // 加载、初始化

   c.newInstance(); // 实例化

Class class1 = Class.forName("com.huang.class.Person ") ;

class1.newInstance();

或者

Person person2 = (Person) Class.forName("com.huang.class.Person").newInstance();

或者

Person person2 = Person.class.newInstance();

 

二)使用ClassLoader类的loadClass方法

Class c = ClassLoader.getSystemClassLoader()  .loadClass("类名"); // 加载

        c.newInstance();// 初始化 ---> 实例化

例如:

Class c = ClassLoader.getSystemClassLoader()

            .loadClass("com.huang.class.Person "); // 加载

  c.newInstance();// 初始化 ---> 实例化

三)使用Constructor类的newInstance方法创建对象

和Class类的newInstance方法很像, java.lang.reflect.Constructor类里也有一个newInstance方法可以创建对象。我们可以通过这个newInstance方法调用有参数的和私有的构造函数。这里需要强调一点private(私有的)修饰的属性或者方法并非绝对的安全,只是对开发者使用的一个约束。属性可以在set()方法中加入约束。

Constructor constructor = Person.class.getConstructor();

Person person3 = constructor.newInstance();

3.使用clone方法创建对象

 

调用一个对象的clone方法,clone方法所做的的操作是直接复制字段的内容,换句话说,这个操作并不管该字段对应的对象实例内容,jvm都会创建一个新同类型对象,将前面对象的内容全部拷贝进去。像这样字段对字段的拷贝(field to field copy)就成为"浅拷贝",clone方法所做的正是"浅拷贝"用clone方法创建对象构造函数不被自动调用。  

JDK中Object# clone()方法的原型是:protected native Object clone() throws  CloneNotSupportedException; 方法修饰符是protected,而不是public。这种访问的不可见性使得我们对Object#clone()方法不可见。所以,必需重写Object的clone方法后才能使用。

值得注意的是 :如果需要使用clone方法,必需实现java.lang.Cloneable接口,并实现其定义的clone方法。不实现Clonable接口就会抛出java.lang.CloneNotSupportedException。

Person person4 = (Person) person4.clone();

4.使用反序列化

 

当我们序列化和反序列化一个对象,jvm会给我们创建一个单独的对象。在反序列化时,jvm创建对象并不会调用任何构造函数。
为了反序列化一个对象,我们需要让我们的类实现Serializable接口

ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));

Person person5 = (Person) in.readObject();

我们从上面的字节码片段可以看到,除了第1个方法,其他4个方法全都转变为invokevirtual(创建对象的直接方法),第一个方法转变为两个调用,new和invokespecial(构造函数调用)。

 

 

你可能感兴趣的:(java,JAVA小知识)