引言

作为Java开发人员,我们每天都会代码中创建对象,但我们通常使用依赖管理系统,比如Spring框架,然后,这里有很多种创建对象的方式,本文就对Java创建对象的几种方式进行总结

五种创建方式

创建方式 特点
使用new关键字 } → 调用了构造函数
使用Class类的newInstance方法 } → 调用了构造函数
使用Constructor类的newInstance方法 } → 调用了构造函数
使用clone方法 } → 没有调用构造函数
使用反序列化 } → 没有调用构造函数

1. new关键字创建

    public static void create1(){
        Object object = new Object();
    }

在Class文件中这段代码如下

0 new #3 <java/lang/Object>
3 dup
4 invokespecial #1 <java/lang/Object.<init>>
7 astore_0
8 return

释义:
其中new指令在java堆上为 object 对象分配内存空间,并将地址压入操作数栈顶
dup指令为复制操作数栈顶值,并将其压入栈顶,也就是说此时操作数栈上有连续相同的两个对象地址
invokespecial指令调用实例初始化方法????)V,注意这个方法是一个实例方法,所以需要从操作数栈顶弹出一个DupTest 对象的引用,也就是说这一步会弹出一个之前入栈的对象地址;
astore_0 指令从操作数栈顶取出 object 对象的引用并存到局部变量表;
最后由return指令结束方法。

2. Class类的newInstance

先获取其Class对象,再调用newInstance方法,这个newInstance方法调用无参的构造函数创建对象。

    public static void create2() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class clazz = Class.forName("com.ycb.createinstance.Student");
        Student student = (Student)clazz.newInstance();
    }

方法对应的字节码

 0 ldc #4 <com.ycb.createinstance.Student>
 2 invokestatic #5 <java/lang/Class.forName>
 5 astore_0
 6 aload_0
 7 invokevirtual #6 <java/lang/Class.newInstance>
10 checkcast #7 <com/ycb/createinstance/Student>
13 astore_1
14 return

3. Constructor类的newInstance

通过Class拿到指定的构造方法,再调用构造方法的newInstance方法创建对象

    public static void create3() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Constructor<Student> constructor = Student.class.getConstructor();
        Student student = constructor.newInstance();
    }

4. clone方法创建

通过clone方法创建对象,并不会调用其构造方法,本质是通过对象内存的复制实现的

    public static void create4() throws CloneNotSupportedException {
        Student student = new Student();
        //要调用clone方法,必须要实现Cloneable接口,并重写其方法
        Student clone =(Student) student.clone();
    }

5. 反序列化创建

为了要反序列化对象,对Class必须要实现Serializable接口
反序列化创建对象,不会调用其构造方法

    public static void create5() throws Exception{
        Student student = new Student();
        //使用序列化方式创建对象
        
        //序列化
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("student.obj"));
        objectOutputStream.writeObject(student);
        objectOutputStream.close();

        //反序列化
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.obj"));
        Student student1 = (Student) in.readObject();
        in.close();
    }