Java创建对象的几种方式

2021-04-08  本文已影响0人  轻轻敲醒沉睡的心灵

平常我们用的最多的就是使用new来创建对象了,这是一种方式;如果我们使用框架的话就直接交给Spring去管理就好了,Spring 底层是使用反射来创建对象的。其他的,知道的基本就少了,下面我们来看看Java中创建对象的方式。
先看一点题外并相关的内容,JVM中的5种方法调用指令:

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

使用 new 来创建对象是最简单的一种方式了,new 是 Java 中的关键字,new 通过为新对象分配内存并返回对该内存的引用来实例化一个类,这个实例化一个类其实就相当于创建了一个对象,因为类也是一种对象;new 也负责调用对象的构造函数,下面是使用 new 来创建对象的代码

Object obj = new Object();

这段代码中,我们在堆区域中分配了一块内存,然后把 obj 对象指向了这块内存区域。
查看一下编译后的字节码

new.png
可以看出,新建对象经历了
new
dup
invokespecial
astore_1
4步指令后才返回。
在 Java 中,我们认为创建一个对象就是调用其构造方法,所以我们使用 new Object() 构造的对象,其实是调用了 Object 类的无参数 的构造方法。但是通过字节码我们发现,对象的创建和调用其构造方法是分开的。
public static void main(String[] args) {    
    new Object();
}

字节码:

new.png
上图中的 astore_1 竟然变成了 pop。
pop.png
这也就是说,new Object() 没有保存对象的局部变量,而是直接把它给消耗掉了。

2. 使用ClassnewInstance()方法来创建对象

这个newInstance()方法指的是Class类中的方法,newInstance()方法会调用无参的构造方法创建对象。

public static void main(String[] args) throws Exception {
    CodeMsg cm = (CodeMsg) Class.forName("com.test.domain.CodeMsg").newInstance();
    // 或者使用
    CodeMsg cm1 = CodeMsg.class.newInstance();
}

上面是newInstance使用的2种方式,第1种多调了forName()方法,forName()是一个静态方法

forName.png
编译后结果:
newInstance.png
可以看出第一种方式多调用了invokestatic指令

new和newInstance区别:

3. 使用Constructor类的newInstance()方法创建对象

Class类的newInstance方法很像,java.lang.reflect.Constructor类里也有一个newInstance方法可以创建对象。我们可以通过这个newInstance方法调用有参数的和私有的构造函数。

Constructor<CodeMsg> constructor = CodeMsg.class.getConstructor();
CodeMsg cm = constructor.newInstance();

这两种newInstance方法就是大家所说的反射。事实上ClassnewInstance方法内部调用ConstructornewInstance方法。这也是众多框架,如Spring、Hibernate、Struts等使用后者的原因。

4. 使用clone()方法创建对象

无论何时我们调用一个对象的clone方法,jvm就会创建一个新的对象,将前面对象的内容全部拷贝进去。用clone方法创建对象并不会调用任何构造函数。
要使用clone方法,我们需要先实现Cloneable接口并实现其定义的clone方法。

public class Person implements Cloneable{
    
    private int age ;
    private String name;
    
    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
    public Person() {}
    public int getAge() {
        return age;
    }
    public String getName() {
        return name;
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return (Person)super.clone();
    }
}

//////////////////////////////////////////
public static void main(String[] args) {    
    Person p = new Person(23, "zhang");
    Person p1 = (Person) p.clone();
}

5. 使用反序列化创建对象

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


参考文章:
https://mp.weixin.qq.com/s/plSHSWe491Q4KJhhNax2Zg
https://www.cnblogs.com/wxd0108/p/5685817.html

上一篇 下一篇

猜你喜欢

热点阅读