Class.newInstance()与new、Constructor.newInstance()的区别
发布日期:2021-07-01 05:57:05
浏览次数:2
分类:技术文章
本文共 3067 字,大约阅读时间需要 10 分钟。
在初始化一个类,生成一个实例的时候,newInstance() 和 new 有什么区别?
用newInstance与用new是区别的, 区别在于创建对象的方式不一样,前者是使用类加载机制,那么为什么会有两种创建对象方式?这个就要从可伸缩、可扩展,可重用等软件思想上解释了。 Java中工厂模式经常使用newInstance来创建对象,因此从为什么要使用工厂模式上也可以找到具体答案。 例如:Class c = Class.forName(“A”);factory = (AInterface)c.newInstance();其中AInterface是A的接口,如果下面这样写,你可能会理解:
String className = "A";Class c = Class.forName(className);factory = (AInterface)c.newInstance();进一步,如果下面写,你可能会理解:
String className = readfromXMlConfig;//从xml 配置文件中获得字符串Class c = Class.forName(className);factory = (AInterface)c.newInstance();上面代码就消灭了A类名称,优点:无论A类怎么变化,上述代码不变,甚至可以更换A的兄弟类B , C , D....等,只要他们继承Ainterface就可以。 从jvm的角度看,我们使用new的时候,这个要new的类可以没有加载;
但是使用newInstance时候,就必须保证:
1、这个类已经加载;
2、这个类已经连接了。
而完成上面两个步骤的正是class的静态方法forName方法,这个静态方法调用了启动类加载器(就是加载java API的那个加载器)。
有了上面jvm上的理解,那么我们可以这样说, newInstance实际上是把new这个方式分解为两步,即,首先调用class的加载方法加载某个类,然后实例化。 这样分步的好处是显而易见的。new者,包括用A.class,在编译期已经确定,不可能在运行期变更,一旦要变更必须改变这部分代码,而newInstance者,Class.forName(String)的参数可以在运行期配置,而无须改动代码, 我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了我们降耦的手段。 newInstance: 弱类型。低效率。 只能调用无参构造。new: 强类型。相对高效。能调用任何public构造。
newInstance() 的参数版本与无参数版本详解
通过反射创建新的类示例,有两种方式:
Class.newInstance()
Constructor.newInstance()
以下对两种调用方式给以比较说明: Class.newInstance() 只能够调用 无参的构造函数,即默认的构造函数; Constructor.newInstance() 可以根据传入的参数,调用 任意构造构造函数。 Class.newInstance() 抛出所有由被调用构造函数抛出的异常。 Class.newInstance() 要求被调用的构造函数是可见的,也即必须是 public类型的; Constructor.newInstance() 在特定的情况下,可以 调用私有的构造函数。 Class A(被调用的示例):public class A { private A() { System.out.println("A's constructor is called."); } private A(int a, int b) { System.out.println("a:" + a + " b:" + b); }}Class B(调用者):
public class B { public static void main(String[] args) { B b=new B(); out.println("通过Class.NewInstance()调用私有构造函数:"); b.newInstanceByClassNewInstance(); out.println("通过Constructor.newInstance()调用私有构造函数:"); b.newInstanceByConstructorNewInstance(); } /*通过Class.NewInstance()创建新的类示例*/ private void newInstanceByClassNewInstance(){ try {/*当前包名为reflect,必须使用全路径*/ A a=(A)Class.forName("reflect.A").newInstance(); } catch (Exception e) { out.println("通过Class.NewInstance()调用私有构造函数【失败】"); } } /*通过Constructor.newInstance()创建新的类示例*/ private void newInstanceByConstructorNewInstance(){ try {/*可以使用相对路径,同一个包中可以不用带包路径*/ Class c=Class.forName("A"); /*以下调用无参的、私有构造函数*/ Constructor c0=c.getDeclaredConstructor(); c0.setAccessible(true); A a0=(A)c0.newInstance(); /*以下调用带参的、私有构造函数*/ Constructor c1=c.getDeclaredConstructor(new Class[]{int.class,int.class}); c1.setAccessible(true); A a1=(A)c1.newInstance(new Object[]{5,6}); } catch (Exception e) { e.printStackTrace(); } } }输入结果如下: 通过Class.NewInstance()调用私有构造函数: 通过Class.NewInstance()调用私有构造函数【失败】 通过Constructor.newInstance()调用私有构造函数: A's constructor is called. a:5 b:6 说明方法newInstanceByClassNewInstance调用失败,而方法newInstanceByConstructorNewInstance则调用成功。 如果被调用的类的构造函数为默认的构造函数,采用Class.newInstance()则是比较好的选择, 一句代码就OK;如果需要调用类的带参构造函数、私有构造函数, 就需要采用Constractor.newInstance(),两种情况视使用情况而定。 不过Java Totorial中推荐采用Constractor.newInstance()。
转载地址:https://panda1234lee.blog.csdn.net/article/details/9009719 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
感谢大佬
[***.8.128.20]2024年05月02日 15时45分14秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
java学习-NIO(五)NIO学习总结以及NIO新特性介绍
2019-05-06
android 定位 获取地理位置 百度地图
2019-05-06
leetcode 155 Min Stack C++
2019-05-06
leetcode 477 Total Hamming Distance C++
2019-05-06
h.264視頻編碼加生成QT7可播放的mp4文件
2019-05-06
mp4封装灵感收集
2019-05-06
ffmpeg 编译指令的理解
2019-05-06
好的生活习惯总结
2019-05-06
笑话收集
2019-05-06
超级程序员神话
2019-05-06
advanced installer制作windows软件安装界面
2019-05-06
操作系统读书笔记
2019-05-06
linux protobuf安装
2019-05-06
go grpc环境搭建
2019-05-06
linux 创建线程时设置优先级
2019-05-06
2017年计划
2019-05-06
【转】电容滤波的两个要点_Detective_ALong_新浪博客
2019-05-06
【转】U-Boot的加载地址分析_Detective_ALong_新浪博客
2019-05-06
【原创】9G10的SMC时序探究_Detective_ALong_新浪博客
2019-05-06