Java创建对象的5种方式简介、语法、举例、对比

2023-08-23 14:51:38 浏览数 (1)

1. 使用new关键字

语法:

代码语言:javascript复制
ClassName objectName = new ClassName();

2. 调用 java.lang.Class 的 newlnstance() 方法

语法:

代码语言:javascript复制
Class c1 = Class.forName("com.java_demo01.day03.Phone");
Phone phone2 = (Phone)c1.newInstance();
// 或者
Class<Phone> c2 = Phone.class;
Phone phone3 = c2.newInstance();

  • newInstance()自jdk 9开始已经弃用
  • 调用 java.lang.Class 类中的 forName() 方法时,需要将要实例化的类的全称(比如 com.java_demo01.day03.Phone)作为参数传递过去,然后再调用 java.lang.Class 类对象的 newInstance() 方法创建对象。
  • 即该方法创建对象需要两步,第一步创建类对象,第二步调用类对象的newInstance()方法
  • newInstance()只能调用public类型的无参构造方法,因此通过此方法实例化对象,则类必须要有无参构造方法,否则将抛出InstantiationException异常。

3. 调用java.lang.reflect.Constructor 类的newInstance()方法

语法:

代码语言:javascript复制
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

Constructor<Phone> constructor = Phone.class.getConstructor(String.class, double.class);
Phone phone5 = constructor.newInstance("OPPO", 1500.0);
phone5.printPhoneInfo();

4. 调用对象的clone()方法

语法:

代码语言:javascript复制
Phone phone4 = (Phone)phone2.clone();

该方法不常用,使用该方法创建对象时,要实例化的类==必须继承 java.lang.Cloneable 接口==。

5. 调用 java.io.ObjectlnputStream 对象的 readObject() 方法

语法:

代码语言:javascript复制
Phone phone = new Phone(); // 调用无参构造方法
// 序列化对象phone
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.obj"));
out.writeObject(phone);
out.close();

// 反序列化
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Phone phone1 = (Phone) in.readObject();
in.close();

上述结果表明通过反序列化创建对象,该对象的属性值为被序列化的对象的属性值。

显式创建对象总结

创建方式

调用何种构造方法

说明

new

任意

最常用

Class.newInstance()

只能调用public无参构造方法

自JDK 9开始弃用

Constructor.newInstance()

任意、私有也可

调用有参构造方法时要在getConstructor中指明参数类型

clone()

不调用任何构造方法

JVM创建对象并将被clone的对象内容拷贝进去;类需要实现Cloneable接口

readObject()

反序列化不调用任何构造方法

类需要实现Serializable接口;JDK序列化、反序列化特别特别耗内存。

因此Java创建对象不一定要通过构造方法

举例

下面例子实现了上述5种创建Java对象的方式:

代码语言:javascript复制
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Phone implements Cloneable, Serializable {
    private String brand;
    private double price;

    public Phone() {
        this("小米", 2000.0);
    }

    public Phone(String brand, double price) {
        this.brand = brand;
        this.price = price;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public void printPhoneInfo() {
        String result = "Phone brand: "   this.brand   " price: "   this.price;
        System.out.println(result);
    }

    public static void main(String[] args){
        try {
            // 使用第一种方式创建无参对象(前提是Phone有无参构造方法,否则报错)
            Phone phone1 = new Phone();
            phone1.printPhoneInfo();
            // 使用第一种方式创建有参对象(前提是Phone有有参构造方法,否则报错)
            Phone phone2 = new Phone("华为", 1999.9);
            phone2.printPhoneInfo();

            // 使用第二种方式创建无参对象(前提Phone有无参构造方法,否则抛出InstantiationException异常)
            Class<Phone> phoneClass = Phone.class;
            Phone phone3 = phoneClass.newInstance();
            phone3.printPhoneInfo();
            // 或者,前提同上
            Class<?> c1 = Class.forName("com.java_demo01.day03.Phone"); // 引号中是类的全称
            Phone phone4 = (Phone)c1.newInstance();
            phone4.printPhoneInfo();
            // 可以通过setBrand和setPrice方法为属性赋值,这里不再演示
           // 使用第三种方式创建对象,该对象可以带有参数,且可以调用私有构造方法
            Constructor<Phone> constructor = Phone.class.getConstructor(String.class, double.class);
            Phone phone5 = constructor.newInstance("OPPO", 1500.0);
            phone5.printPhoneInfo();

            // 使用第三种方式创建对象,该对象的属性和被clone的对象属性相同,但是两个不同的对象
            Phone phone6 = (Phone)phone2.clone();
            phone6.printPhoneInfo();

            // 使用第四种方式创建对象,该对象的属性和被序列化的对象属性相同,但是两个不同的对象
            // 序列化对象phone
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.obj"));
            out.writeObject(phone2);
            out.close();

            // 反序列化
            ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
            Phone phone7 = (Phone) in.readObject();
            in.close();
            phone7.printPhoneInfo();
        } catch (IllegalAccessException |
                IOException |
                ClassNotFoundException |
                InstantiationException |
                CloneNotSupportedException |
                InvocationTargetException |
                NoSuchMethodException e) {
            e.printStackTrace();
        }

    }
}
// 输出结果
Phone brand: 小米 price: 2000.0
Phone brand: 华为 price: 1999.9
Phone brand: 小米 price: 2000.0
Phone brand: 小米 price: 2000.0
Phone brand: OPPO price: 1500.0
Phone brand: 华为 price: 1999.9
Phone brand: 华为 price: 1999.9

0 人点赞