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

简介: 在初始化一个类,生成一个实例的时候,newInstance() 和 new 有什么区别?

在初始化一个类,生成一个实例的时候,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()。


目录
相关文章
|
5月前
|
Java 测试技术
Java反射之Method的invoke方法详解
Java反射之Method的invoke方法详解
|
5月前
|
Java
Class.forName()方法总结
Class.forName()方法总结
|
6月前
|
Java
Class.forName和ClassLoader到底有啥区别
Class.forName和ClassLoader到底有啥区别
25 0
|
6月前
|
缓存 前端开发 JavaScript
方法 constructor()
方法 constructor() 是 JavaScript 中构造函数的一个特殊方法,它用于创建和初始化对象。当使用 new 操作符创建一个对象时,构造函数的 constructor 方法会被自动调用。在 constructor 方法中,可以设置对象的属性和方法,以及执行一些初始化操作。
59 7
|
Java API
Java反射(Constructor)(二)
Constructor类是Java反射中重要的类,它是对类中构造器的描述的类。类似于Method(对类中方法的描述的类),Field(对类中属性的描述的类),我们通过创建Constructor的对象实例,就可以创建源对象。
141 1
Java反射(Constructor)(二)
JAVA中子类使用super.getClass()方法
JAVA中子类使用super.getClass()方法
|
Java 数据库连接 API
Java“ Class.forName()”和“ Class.forName()newInstance()”之间有什么区别?
Java“ Class.forName()”和“ Class.forName()newInstance()”之间有什么区别?
104 0
|
缓存 安全 Java
Java反射包下的Method类中的Invoke方法
Java反射包下的Method类中的Invoke方法
167 0
Java反射包下的Method类中的Invoke方法
|
前端开发 Java 关系型数据库
Class.forName 和 ClassLoader 到底有啥区别?
Class.forName 和 ClassLoader 到底有啥区别?
136 0