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


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

    原文地址:Java创建对象的5种方式简介、语法、举例、对比

    1. 使用new关键字

    语法:

    ClassName objectName = new ClassName();
    
    • 1

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

    语法:

    Class c1 = Class.forName("com.java_demo01.day03.Phone");
    Phone phone2 = (Phone)c1.newInstance();
    // 或者
    Class<Phone> c2 = Phone.class;
    Phone phone3 = c2.newInstance();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 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()方法

    语法:

    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();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

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

    语法:

    Phone phone4 = (Phone)phone2.clone();
    
    • 1

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

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

    语法:

    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();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

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

    显式创建对象总结

    创建方式调用何种构造方法说明
    new任意最常用
    Class.newInstance()只能调用public无参构造方法自JDK 9开始弃用
    Constructor.newInstance()任意、私有也可调用有参构造方法时要在
    getConstructor中指明参数类型
    clone()不调用任何构造方法JVM创建对象并将被clone的
    对象内容拷贝进去;
    类需要实现Cloneable接口
    readObject()反序列化不调用任何构造方法类需要实现Serializable接口;
    JDK序列化、反序列化特别特别耗内存。

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

    举例

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

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
  • 相关阅读:
    使用 OpenTelemetry 构建 .NET 应用可观测性(2):OpenTelemetry 项目简介
    C++ permutation排列算法详解(深入了解,一文学会)
    TensorRT开发环境搭建
    cesium 之 flyTo、setView、lookat
    接口测试实战| GET/POST 请求区别详解
    思想总结
    Linux串口断帧处理
    鲜花静态HTML网页作业作品 大学生鲜花网页设计制作成品 简单DIV CSS布局网站
    音频存储格式wav介绍与解析
    【ijkplayer】编译 Android 版本的 ijkplayer ⑦ ( 使用 AS 打开源码 | 重新设置 AGP 和 Gradle 版本号 | 设置依赖仓库 | 设置依赖 | 编译运行 )
  • 原文地址:https://blog.csdn.net/weixin_46334596/article/details/127722635