Java中5种创建对象的不同方法_云起网
您现在的位置是:首页 > 技术文章 >

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

未知 2020-09-10 09:49
作为Java开发人员,我们通常每天创建大量对象,但我们总是使用新的或依赖管理系统(如Spring)来创建这些对象。然而,我们将在本文中研究创建对象的更多方法。

作为Java开发人员,我们通常每天创建大量对象,但我们总是使用新的或依赖管理系统(如Spring)来创建这些对象。然而,我们将在本文中研究创建对象的更多方法。
在Java中总共有5种创建对象的核心方法,下面将介绍它们的示例,然后是创建对象那一行的字节码。然而,有很多API为我们创建对象,但是这些API也将间接地使用这5种核心方式之一,例如SpringBeanFactory。
 
如果要执行最后给出的程序,您将看到方法1、2、3使用构造函数创建对象,而4,5不调用构造函数来创建对象。
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()方法调用no-arg构造函数来创建对象。
 
我们可以通过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.使用Constructor类的newInstance()方法
类似于Class类的newInstance()方法,java.lang.reflect.Constructor类中有一个newInstance()方法,我们可以使用它来创建对象。我们还可以使用这个newInstance()方法调用参数化构造函数和私有构造函数。
 
Constructor<Employee> constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();

111: invokevirtual  #80  // Method java/lang/reflect/Constructor.newInstance:([Ljava/lang/Object;)Ljava/lang/Object;
 
两个newInstance()方法都被称为创建对象的反射方式。实际上,Class类的newInstance()方法内部使用了Constructor类的newInstance()方法。这就是为什么后一种方法是首选的,并被Spring、Hibernate、Struts等不同框架所使用,以了解两种newInstance()方法之间的差异。在Java中通过反射创建对象.
 
4.使用clone()方法:
每当我们对任何对象调用clone()时,JVM实际上都会为我们创建一个新对象,并将前一个对象的所有内容复制到其中。使用克隆方法创建对象不调用任何构造函数。
 
要在对象上使用克隆()方法,我们需要实现cloneable,并在其中定义cloneable()方法。
 
Employee emp4 = (Employee) emp3.clone();
 
162: invokevirtual #87  // Method org/programming/mitra/exercises/Employee.clone ()Ljava/lang/Object;

 
Java clone是Java社区中最有争议的话题,它当然有其缺点,但它仍然是创建任何对象副本的最流行和最简单的方法。
我在一篇长达3篇的文章中详细介绍了克隆。

 Java Cloning And Types Of Cloning (Shallow And Deep) In Details With Example,
 
Java Cloning - Copy Constructor Versus Cloning,
Java Cloning - Even Copy Constructors Are Not Sufficient
 
5.使用反序列化:
每当我们序列化对象,然后反序列化对象JVM为我们创建一个单独的对象。在反序列化中,JVM不使用任何构造函数来创建对象。要反序列化对象,我们需要在类中实现可序列化接口。
 
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();
 
261: invokevirtual  #118   // Method java/io/ObjectInputStream.readObject:()Ljava/lang/Object;
 
正如我们在上面的字节码中所看到的,所有4个方法调用都被转换为Invokevirtual(对象创建由这些方法直接处理),除了第一个方法被转换为两个调用,一个是new,另一个是invokespecial
 

例子:
下面的代码为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 boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return Objects.equals(name, employee.name);
    }
 
    @Override
    public int hashCode() { return Objects.hash(name); }
 
    @Override
    public String toString() { return String.format("Employee{name='%s'}", 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 {
 
        // 1. Using new keyword
        Employee emp1 = new Employee();
        emp1.setName("emp1");
 
 
        // 2. Using Class class's newInstance() method
        Employee emp2 = Employee.class.newInstance();
        emp2.setName("emp2");
 
 
        // 3. Using Constructor class's newInstance() method
        Constructor<Employee> constructor = Employee.class.getConstructor();
        Employee emp3 = constructor.newInstance();
        emp3.setName("emp3");
 
        // 4. Using clone() method
        Employee emp4 = (Employee) emp3.clone();
        emp4.setName("emp4");
 
 
        // Serialization
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.obj"))) {
            out.writeObject(emp4);
        }
 
        // 5. Using Deserialization
        Employee emp5;
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"))) {
            emp5 = (Employee) in.readObject();
            emp5.setName("emp5");
        }
 
        System.out.println(emp1 + ", hashcode : " + emp1.hashCode());
        System.out.println(emp2 + ", hashcode : " + emp2.hashCode());
        System.out.println(emp3 + ", hashcode : " + emp3.hashCode());
        System.out.println(emp4 + ", hashcode : " + emp4.hashCode());
        System.out.println(emp5 + ", hashcode : " + emp5.hashCode());
    }
}
输出结果:
 
Employee Constructor Called...
Employee Constructor Called...
Employee Constructor Called...
Employee{name='emp1'}, hashcode : 3117192
Employee{name='emp2'}, hashcode : 3117193
Employee{name='emp3'}, hashcode : 3117194
Employee{name='emp4'}, hashcode : 3117195
Employee{name='emp5'}, hashcode : 3117196


参考
https://dzone.com/articles/5-different-ways-to-create-objects-in-java-with-ex

(吃猫的鱼)