美文网首页
Java创建对象的几种方式

Java创建对象的几种方式

作者: 轻轻敲醒沉睡的心灵 | 来源:发表于2021-04-08 18:20 被阅读0次

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

  • invokestatic:该指令用于调用静态方法,即使用 static 关键字修饰的方法;
  • invokespecial:该指令用于三种场景:调用实例构造方法,调用私有方法(即 private 关键字修饰的方法)和父类方法(即 super 关键字调用的方法);
  • invokeinterface:该指令用于调用接口方法,在运行时再确定一个实现此接口的对象;
  • invokevirtual:该指令用于调用虚方法(就是除了上述三种情况之外的方法);
  • `invokedynamic1:在运行时动态解析出调用点限定符所引用的方法之后,调用该方法;在 JDK 1.7 中提出,主要用于支持 JVM 上的动态脚本语言(如 Groovy,Jython 等)。

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 类的无参数 的构造方法。但是通过字节码我们发现,对象的创建和调用其构造方法是分开的。
  • new表示在堆中创建一个对象,并把对象的引用推入栈中
  • dup 会复制栈上的最后一个元素,然后再次将其推入栈;因此,如果在栈上有一个对象引用,并且调用了 dup,则现在在栈上有对该对象的两个引用。
    关于dup指令的问题,参考关于JVM字节码中dup指令的问题
  • invokespecial 表示调用对象无参数的构造方法进行初始化。JVM指令集中,invokespecial指令格式如下:
    invokespecial.png
    看一下操作数栈,需要一个objectref引用(对象的地址),后面是可选的参数;由于初始化没有返回值,调用之后没有东西入栈(用...表示没有入栈)。没有返回值,调用之后没有东西入栈(用...表示没有入栈)。
  • astore_1 就会把操作数栈顶的那个引用消耗掉,保存到指定的局部变量去。
    若不创建局部变量,只新建对象,
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指令
  • ldc的意思是把常量池中的引用推入到当前堆栈中
  • checkcast含义就是进行类型转换,因为 newInstance 生成的是一个 Object 的对象,所以我们需要把它转换为我们指定的类型

new和newInstance区别:

  • newInstance(): 弱类型,低效率,只能调用无参构造。
    使用newInstance()方法的时候,必须保证这个类已经加载,这由Class类的静态方法forName()完成
  • new: 强类型,相对高效,能调用任何public构造。

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

相关文章

  • 16、Java创建对象有几种方式?

    Java创建对象有几种方式? java中提供了以下四种创建对象的方式: 1、new创建新对象; 2、通过反射机制;...

  • 设计模式-工厂模式

    在Java语言中,我们通常由以下几种创建对象的方式:(1)使用new关键字直接创建对象(2)通过反射机制创建对象(...

  • java创建对象的几种方式

    java中创建对象有几种方式? 使用new关键字 如 User user=new User(); 执行这条语句,j...

  • Java创建对象的几种方式

    一、使用new关键字 这是我们最常见的也是最简单的创建对象的方式,通过这种方式我们还可以调用任意的构造函数(无参的...

  • Java创建对象的几种方式

    平常我们用的最多的就是使用new来创建对象了,这是一种方式;如果我们使用框架的话就直接交给Spring去管理就好了...

  • 创建对象只是开辟个堆内存那么简单吗?

    java对象 对象的创建 java的对象是在运行时创建的,创建对象的的触发条件有以下几种: 用new语句创建对象,...

  • Java对象创建与内存分布

    本文主要讲述Java对象在虚拟机中创建,分配内存,初始化的过程,以及分配内存,引用对象的几种常见方式。 对象创建 ...

  • JAVA创建和销毁对象的方法

    姓名: 李小娜 [嵌牛导读] :本篇文章主要介绍了JAVA创建和销毁对象的方法 [嵌牛鼻子] :创建对象的几种方式...

  • java反射详解

    ## 引言 ### java中创建对象有几种方式? #### 1.使用new关键字 #### 2.使用clone方...

  • Java中的clone方法你知道多少?

    我们知道clone方法在Java中是一个复制对象的方法,那么Java有几种创建对象的方式呢? 1.通过new关键字...

网友评论

      本文标题:Java创建对象的几种方式

      本文链接:https://www.haomeiwen.com/subject/kyiukltx.html