Class.newInstance()学习

本文详细解析了Java中newInstance和new创建对象的区别,包括它们的使用场景、优势及注意事项,通过实例代码展示了如何利用newInstance实现灵活的类加载与对象创建。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在初始化一个类,生成一个实例的时候;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的加载方法加载某个类,然后实例化。 
  这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了我们降耦的手段。 

       newInstance: 弱类型。低效率。只能调用无参构造。 
       new: 强类型。相对高效。能调用任何public构造。Class.newInstance()学习
<think>嗯,用户问的是关于Java反射的代码示例,他们可能是在学习反射机制或者需要动态加载类、调用方法。首先,我需要分析用户提供的代码片段,然后解释每一行的作用。用户可能对反射的基本概念有所了解,但需要更深入的理解每个步骤的具体实现和潜在应用场景。 首先,Class.forName("com.chenshuyi.reflect.Apple")这里是通过类的全限定名获取Class对象,这一步可能会抛出ClassNotFoundException,用户可能需要注意异常处理。接下来,getMethod方法获取setPrice方法,参数是int.class,说明该方法接受一个int参数。然后获取无参构造器并创建实例,最后调用method.invoke来设置价格。 用户可能的疑问包括:为什么使用Class.forName?getMethod和getConstructor的参数规则是什么?invoke方法的使用注意事项?还有可能涉及到反射的性能问题或者安全限制。需要解释每个步骤的作用,以及可能抛出的异常,比如NoSuchMethodException或者IllegalAccessException。 另外,用户可能没有意识到反射的潜在问题,比如破坏封装性、性能开销,或者如何在实际应用中合理使用反射。可能需要给出最佳实践的建议,比如缓存反射对象以提高性能,或者使用setAccessible方法处理私有成员时的注意事项。 最后,代码示例中的类名是Apple,方法setPrice可能是一个设置价格的方法,用户可能是在练习如何动态调用对象的setter方法,或者是在框架开发中需要动态处理对象。需要强调反射的灵活性和适用场景,比如框架设计、动态代理等,同时提醒其缺点。</think>以下是通过Java反射机制操作对象的代码解析,按执行步骤分层说明: **1. 类加载阶段** `Class clz = Class.forName("com.chenshuyi.reflect.Apple");` - 使用全限定类名动态加载`Apple`类 - 触发**类初始化**过程(执行static代码块) - 返回`Class`对象作为类元数据入口 **2. 方法元数据获取** `Method method = clz.getMethod("setPrice", int.class);` - 精确匹配参数类型`int`的`public`方法 - 方法签名验证流程: $$ \text{方法名} + \text{参数类型列表} \rightarrow \text{唯一标识符} $$ - 未找到方法时抛出`NoSuchMethodException` **3. 对象实例化过程** ```java Constructor constructor = clz.getConstructor(); Object object = constructor.newInstance(); ``` - 获取无参构造器(必须显式声明) - 通过`newInstance()`创建对象(等效于`new Apple()`) - 底层实现: `Unsafe.allocateInstance()` + 构造器代码执行 **4. 动态方法调用** `method.invoke(object, 4);` - 参数解包与类型转换:自动将`int 4`装箱为`Integer` - 调用等效于: ```java ((Apple)object).setPrice(4); ``` - 性能损耗:较直接调用慢50-100倍(JIT优化前) **关键注意事项**: 1. 访问控制:需`setAccessible(true)`才能调用非public方法 2. 类型安全:`invoke()`参数错误会导致`IllegalArgumentException` 3. 推荐做法:缓存高频访问的`Method/Constructor`对象 **典型应用场景**: - Spring框架的依赖注入 - JUnit测试框架的方法扫描 - ORM框架的实体类映射 示例代码完整执行后,等价于以下直接调用: ```java Apple apple = new Apple(); apple.setPrice(4); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值