创建对象的几种方式

概述

①、使用new关键字;

②、使用Class类的newInstance方法;

③、使用Constructor类的newInstance方法;

④、使用Object类的clone方法;

⑤、使用反序列化的方式;

 

详解

1.使用Class类的newInstance方法

这个newInstance方法调用无参的构造器创建对象

 private static void demo1() {
        try {
            Entity entity = Entity.class.newInstance();
            entity.name = ".class";
            System.out.println(entity);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private static void demo2() {
        try {
            Class<?> aClass = Class.forName("com.learn.reflection.Entity");
            Entity o = (Entity) aClass.newInstance();
            o.name = "forName";
            System.out.println(o);


        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
private static void demo3() {
        Entity entity = new Entity();
        try {
            Entity entity1 = entity.getClass().newInstance();
            entity1.name = "getClass";
            System.out.println(entity1);

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

Class.forName() 与 xxx.class的区别

所有的类都是在对其第一次使用时,动态加载到 JVM。当程序创建第一个对类的静态成员的引用时,就会加载这个类。这也证明了构造器也是类的静态方法,即使在构造器之前并没有 static 关键字。因此,使用 new 操作符创建类的对象也会被当作对类的静态成员的引用。

因此 Java 程序在他开始运行之前并非被完全加载,其各个部分是在需要时才加载的。

类加载器首先槛车这个类的 Class 对象是否已经加载。如果尚未加载,默认的类加载器就会根据类名称查找 .class 文件。在这个类的字节码被加载时,它们会接收验证,以确保其没有被破坏。

Class 对象尽在需要的时候才被加载。static 初始化是在类加载时进行的。

对于 Class.forName(),这个方法是 Class 类的一个 static 成员。Class 对象就和其他对象一样,我们可以获取并操作他的引用。forName() 是取得 Class 对象引用的一种方法。他是用一个包含目标类的文本名的 String 作为输入参数,返回一个 Class 对象的引用。forName() 方法发现某个累还没被加载,就会主动去加载这个类,在加载过程中,该类的是 static 子句将会被执行。

Java 还提供了另一种方法来生成对 Class 对象的引用,即使用类字面常量。形如:xxx.class 的形式。但是这种形式创建 Class 对象引用时,不会自动初始化 Class 对象。初始化被延迟到了对静态方法或者非常数静态域首次引用时才执行。

2.使用Constructor类的newInstance方法;

public static void main(String[] args) {
        try {
            Entity entity = Entity.class.getConstructor(String.class).newInstance("parameter");
            System.out.println(entity);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

两种newInstance方法的区别

  

     Class类位于java的lang包中,而构造器类是java反射机制的一部分。

 

  Class类的newInstance只能触发无参数的构造方法创建对象,而构造器类的newInstance能触发有参数或者任意参数的构造方法来创建对象。

 

  Class类的newInstance需要其构造方法是共有的或者对调用方法可见的,而构造器类的newInstance可以在特定环境下调用私有构造方法来创建对象。

 

  Class类的newInstance抛出类构造函数的异常,而构造器类的newInstance包装了一个InvocationTargetException异常。


  Class类本质上调用了反射包构造器类中无参数的newInstance方法,捕获了InvocationTargetException,将构造器本身的异常抛出。

 

其实也可以使用类加载器获取Class对象

 private void demo4() {
        ClassLoader classLoader = this.getClass().getClassLoader();
        try {
            Class<?> aClass = classLoader.loadClass("com.learn.reflection.Entity");
            Entity o = (Entity) aClass.newInstance();
            o.name = "ClassLoader";
            System.out.println(o);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

 

3.clone

1. cloneable

clone() 是 Object 的 protected 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法。

clone() 方法并不是 Cloneable 接口的方法,而是 Object 的一个 protected 方法。Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 CloneNotSupportedException。

 

  @Override
    //浅拷贝 拷贝对象和原始对象的引用类型引用同一个对象
    protected Entity clone() throws CloneNotSupportedException {
        return (Entity)super.clone();
    }
public static void main(String[] args) throws CloneNotSupportedException {
        Entity entity = new Entity();
        entity.name = "clone";
        Entity clone = entity.clone();
        System.out.println(clone);
    }

4.序列化

需要实现Serializable ,它是一个标识性接口

public static void main(String[] args) throws CloneNotSupportedException {
        Entity entity = new Entity();
        entity.name="xuliehua";
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:/test.class"))) {
            oos.writeObject(entity);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 反序列化
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:/test.class"))) {
            Entity entity1 = (Entity) ois.readObject();
            System.out.println("反序列化:" + entity1);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值