资讯专栏INFORMATION COLUMN

Java中创建对象的5种不同方法

Bmob / 2279人阅读

摘要:使用关键字这是最常见的创建对象的方法,并且也非常简单。我们可以通过用以下方式创建对象或者使用构造函数类的方法与使用类的方法相似,类中有一个可以用来创建对象的函数方法。在反序列化中,虚拟机不会使用任何构造函数来创建对象。

作为Java开发者,我们每天都会创建大量的对象,但是,我们总是使用管理依赖系统(如Spring框架)来创建这些对象。其实还有其他方法可以创建对象,在接下来的文章中我会进行详细介绍。

1.使用new关键字

这是最常见的创建对象的方法,并且也非常简单。通过使用这种方法我们可以调用任何我们需要调用的构造函数。

Employee emp1 = new Employee();
0: new           #19          // class org/programming/mitra/exercises/Employee
 3: dup
 4: invokespecial #21          // Method org/programming/mitra/exercises/Employee."":()V
2.使用class类的newInstance方法

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

我们可以通过newInstance() 用以下方式创建对象:

Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee").newInstance();

或者

Employee emp2 = Employee.class.newInstance();
51: invokevirtual    #70    // Method java/lang/Class.newInstance:()Ljava/lang/Object;
3.使用构造函数类的 newInstance方法

与使用class类的newInstance方法相似,java.lang.reflect.Constructor类中有一个可以用来创建对象的newInstance()函数方法。通过使用这个newInstance方法我们也可以调用参数化构造函数和私有构造函数。

Constructor constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();
111: invokevirtual  #80  // Method java/lang/reflect/Constructor.newInstance:([Ljava/lang/Object;)Ljava/lang/Object;

这些 newInstance() 方法被认为是创建对象的反射手段。实际上,内部类的newInstance()方法使用构造函数类的 newInstance() 方法。这就是为什么后者是首选并且使用不同的框架如Spring, Hibernate, Struts等。

4.使用clone方法

实际上无论何时我们调用clone方法,JAVA虚拟机都为我们创建了一个新的对象并且复制了之前对象的内容到这个新的对象中。使用 clone方法创建对象不会调用任何构造函数。

为了在对象中使用clone()方法,我们需要在其中实现可克隆类型并定义clone方法。

Employee emp4 = (Employee) emp3.clone();
162: invokevirtual #87  // Method org/programming/mitra/exercises/Employee.clone ()Ljava/lang/Object;
5.使用反序列化

无论何时我们对一个对象进行序列化和反序列化,JAVA虚拟机都会为我们创建一个多带带的对象。在反序列化中,JAVA虚拟机不会使用任何构造函数来创建对象。

对一个对象进行序列化需要我们在类中实现可序列化的接口。

ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();
261: invokevirtual  #118   // Method java/io/ObjectInputStream.readObject:()Ljava/lang/Object;

正如我们在以上的字节代码片段中所看到的,除第一种被转换为一个新的函数和一个 invokespecial 指令以外,其它4种方法都被调用并转换为invokevirtual。

示例

让我们来看看准备创建对象的 Employee 类:

class Employee implements Cloneable, Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    public Employee() {
        System.out.println("Employee Constructor Called...");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Employee other = (Employee) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    @Override
    public String toString() {
        return "Employee [name=" + name + "]";
    }
    @Override
    public Object clone() {
        Object obj = null;
        try {
            obj = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return obj;
    }
}

在下面的Java程序中我们用5种方式来创建 Employee对象。

public class ObjectCreation {
    public static void main(String... args) throws Exception {
        // By using new keyword
        Employee emp1 = new Employee();
        emp1.setName("Naresh");
        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("Rishi");
        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("Yogesh");
        System.out.println(emp3 + ", hashcode : " + emp3.hashCode());
        // By using clone() method
        Employee emp4 = (Employee) emp3.clone();
        emp4.setName("Atul");
        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("Akash");
        System.out.println(emp5 + ", hashcode : " + emp5.hashCode());
    }
}

此程序输出结果如下:

Employee Constructor Called...
Employee [name=Naresh], hashcode : -1968815046
Employee Constructor Called...
Employee [name=Rishi], hashcode : 78970652
Employee Constructor Called...
Employee [name=Yogesh], hashcode : -1641292792
Employee [name=Atul], hashcode : 2051657
Employee [name=Akash], hashcode : 63313419

本文译自:Dzone 译者:慧都控件网-慧都小艺

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64968.html

相关文章

  • Java String类笔记

    摘要:这两个操作符都是编译器默认引入了类,最后都调用方法返回对象,临时对象被回收,因此效率极为低下 Java String类笔记 声明 文章均为本人技术笔记,转载请注明出处https://segmentfault.com/u/yzwall String的不可变性 String的不可变性 // String declaration public final class String ...

    Vicky 评论0 收藏0
  • JS中创对象设计模式

    摘要:构造函数模式定义构造函数模式是语言创建对象的通用方式。但两种语言用构造函数创建对象的方式略有不同在中没有类的概念,函数即为一等公民,因此,不必显式声明某个类,直接创建构造函数即可,类的方法和属性在构造函数中或原型对象上处理。 工厂模式 定义:工厂模式非常直观,将创建对象的过程抽象为一个函数,用函数封装以特定接口创建对象的细节。通俗地讲,工厂模式就是将创建对象的语句放在一个函数里,通...

    Galence 评论0 收藏0
  • Java8中创Stream 流方式以及 Stream 中间操作

    摘要:一创建里流的四种方式第一种通过得方法串行流或者方法并行流创建。终止操作时一次性全部处理,称为延迟加载筛选切片过滤中建操作。终止操作只有执行终止操作才会执行全部。即延迟加载结果中建操作。截断流,使其元素不超过给定数量。返回流中最大值。 Stream api **Stream api 是java8 中提供的对集合处理的api , 对数据进行一系列的中间操作,元数据不会发生改变 ...

    0xE7A38A 评论0 收藏0
  • Java虚拟机中,字符串常量到底存放在哪

    摘要:的三种常量池此外,有三种常量池,即字符串常量池又叫全局字符串池文件常量池运行时常量池。开始虚拟机把字符串常量池位置从永久代挪到堆,又彻底取消,把诸如之类的元数据都挪到堆之外管理。 前言 前阵子和朋友讨论一个问题: 字符串常量归常量池管理,那比如 String str = abc; abc这个对象是放在内存中的哪个位置,是字符串常量池中还是堆? 这句代码的abc当然在常量池中,只有n...

    lewinlee 评论0 收藏0
  • 44个Java代码性能优化总结

    摘要:代码优化的最重要的作用应该是避免未知的错误。此举能够使性能平均提高。抛出异常首先要创建一个新的对象,接口的构造函数调用名为的本地同步方法,方法检查堆栈,收集调用跟踪信息。异常只能用于错误处理,不应该用来控制程序流程。 showImg(https://segmentfault.com/img/remote/1460000015379073); 代码优化的最重要的作用应该是:避免未知的错误...

    YanceyOfficial 评论0 收藏0

发表评论

0条评论

Bmob

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<