Class.newInstance()和new、Constructor.newInstance()的区别

本文转载自

https://blog.csdn.net/panda1234lee/article/details/9009719 

https://blog.csdn.net/qq_29631069/article/details/79177543

 

用newInstance与用new是区别的,区别在于创建对象的方式不一样,前者是使用类加载机制,那么为什么会有两种创建对象方式?这个就要从可伸缩、可扩展,可重用等软件思想上解释了。 

从jvm的角度看,我们使用new的时候,这个要new的类可以没有加载; 但是使用newInstance时候,就必须保证:

1、这个类已经加载;

2、这个类已经连接了。

而完成上面两个步骤的正是class的静态方法forName方法,这个静态方法调用了启动类加载器(就是加载java API的那个加载器)。有了上面jvm上的理解,那么我们可以这样说,newInstance实际上是把new这个方式分解为两步,即,首先调用class的加载方法加载某个类,然后实例化。 

这样分步的好处是显而易见的。new者,包括用A.class,在编译期已经确定,不可能在运行期变更,一旦要变更必须改变这部分代码,而newInstance者,Class.forName(String)的参数可以在运行期配置,而无须改动代码,我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了我们降耦的手段。 

 

通过反射创建新的类示例,有两种方式: 

Class.newInstance()

Constructor.newInstance()
其中
Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数; 
Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数。 

Class.newInstance() 抛出所有由被调用构造函数抛出的异常。 

Class.newInstance() 要求被调用的构造函数是可见的,也即必须是public类型的; 
Constructor.newInstance() 在特定的情况下,可以调用私有的构造函数。

 

举例: 

public class Demo {
    public static void main(String[] args) {
        try {

            /**
             *  Class.forName(String):要求JVM查找并加载String指定的类
             *  返回String串指定的类
             */
            Class clazz = Class.forName("com.yao.test.sjmstest.Demo");   
            Demo demo = (Demo) clazz.newInstance();
            demo.method(demo);

           //new方式
            Demo demo1 = new Demo();
            demo1.method(demo1);


        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
 
    public void method(Demo demo) {
        System.out.println(demo);
    }
}

 

运行结果:

com.yao.test.sjmstest.Demo@1d44bcfa
com.yao.test.sjmstest.Demo@266474c2

可见两种方法得到的对象并没有什么区别

 

实际应用

接口:

public interface ParentPrint {
    void print(String classname);
}

子类A:

public class A implements ParentPrint{
    public void print(String classname) {
        System.out.println("Clas A");
        System.out.println(classname);
    }
}

 

子类B:

public class B implements ParentPrint {
    public void print(String classname) {
        System.out.println("Class B");
        System.out.println(classname);
    }
}

工厂类:

public class PrintFactory {
    public static ParentPrint getParentPrint(Class clazz) {

        try {

            ParentPrint print = (ParentPrint) clazz.newInstance();
            return print;
        

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

测试类:

public class Main {
    public static void main(String[] args) {
       
        ParentPrint print = PrintFactory.getParentPrint(A.class);
        print.print("A");
 

        ParentPrint print1 = PrintFactory.getParentPrint(B.class);
        print.print("B");
    }
}

运行结果:

Clas A
A
Clas A
B

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值