Class.newInstance与new 调用构造函数实例化创建一个实例有什么不同吗

转载:/mianshiti/it/java/7148/
newInstance: 弱类型。低效率。只能调用无参构造。new: 强类型。相对高效。能调用任何public构造。newInstance()是实现IOC、反射、面对接口编程 和 依赖倒置 等技术方法的必然选择,new 只能实现具体类的实例化,不适合于接口编程。newInstance()里面就是通过这个类的默认构造函数构建了一个对象,如果没有默认构造函数就抛出InstantiationException, 如果没有访问默认构造函数的权限就抛出IllegalAccessException。
在初始化一个类,生成一个实例的时候;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 = readfromXMlC//从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()方法,这个静态方法调用了启动类加载器(就是加载javaAPI的那个加载器)。有了上面jvm上的理解,那么我们可以这样说,newInstance实际上是把new这个方式分解为两步,即,首先调用class的加载方法加载某个类,然后实例化。这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了我们降耦的手段。
阅读(...) 评论()转载:/shuoit/659.html
用最简单的描述来区分new关键字和newInstance()方法的区别:newInstance: 弱类型。低效率。只能调用无参构造。new: 强类型。相对高效。能调用任何public构造。
newInstance( )是一个方法,而new是一个关键字,其次,Class下的newInstance()的使用有局限,因为它生成对象只能调用无参的构造函数,而使用new关键字生成对象没有这个限制。Class.forName("")返回的是类Class.forName("").newInstance()返回的是object
作为Java开发者,我们每天创建很多对象,但我们通常使用依赖管理系统,比如Spring去创建对象。然而这里有很多创建对象的方法,我们会在这篇文章中学到。
Java中有5种创建对象的方式,下面给出它们的例子还有它们的字节码:
使用new关键字
}&调用了构造函数
使用Class类的newInstance方法
} &调用了构造函数
使用Constructor类的newInstance方法
}&调用了构造函数
使用clone方法
} &没有调用构造函数
使用反序列化
} &没有调用构造函数
如果你运行了末尾的的程序,你会发现方法1,2,3用构造函数创建对象,方法4,5没有调用构造函数。
1.使用new关键字
这是最常见也是最简单的创建对象的方式了。通过这种方式,我们可以调用任意的构造函数(无参的和带参数的)。
Employee emp1 = new Employee();
// class org/programming/mitra/exercises/Employee
4: invokespecial #21
// Method org/programming/mitra/exercises/Employee."":()V
2.使用Class类的newInstance方法
我们也可以使用Class类的newInstance方法创建对象。这个newInstance方法调用无参的构造函数创建对象。
我们可以通过下面方式调用newInstance方法创建对象:
Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee").newInstance();
Employee emp2 = Employee.class.newInstance();
51: invokevirtual
// Method java/lang/Class.newInstance:()Ljava/lang/O
3.使用Constructor类的newInstance方法
和Class类的newInstance方法很像, java.lang.reflect.Constructor类里也有一个newInstance方法可以创建对象。我们可以通过这个newInstance方法调用有参数的和私有的构造函数。
Constructor&Employee& constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();
111: invokevirtual
// Method java/lang/reflect/Constructor.newInstance:([Ljava/lang/O)Ljava/lang/O
  这两种newInstance方法就是大家所说的反射。事实上Class的newInstance方法内部调用Constructor的newInstance方法。这也是众多框架,如Spring、Hibernate、Struts等使用后者的原因。
4.使用clone方法
无论何时我们调用一个对象的clone方法,jvm就会创建一个新的对象,将前面对象的内容全部拷贝进去。用clone方法创建对象并不会调用任何构造函数。
要使用clone方法,我们需要先实现Cloneable接口并实现其定义的clone方法。
Employee emp4 = (Employee) emp3.clone();
162: invokevirtual #87
// Method org/programming/mitra/exercises/Employee.clone ()Ljava/lang/O
5.使用反序列化
当我们序列化和反序列化一个对象,jvm会给我们创建一个单独的对象。在反序列化时,jvm创建对象并不会调用任何构造函数。为了反序列化一个对象,我们需要让我们的类实现Serializable接口
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();
261: invokevirtual
// Method java/io/ObjectInputStream.readObject:()Ljava/lang/O
我们从上面的字节码片段可以看到,除了第1个方法,其他4个方法全都转变为invokevirtual(创建对象的直接方法),第一个方法转变为两个调用,new和invokespecial(构造函数调用)。
让我们看一看为下面这个Employee类创建对象:
class Employee implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
public Employee() {
System.out.println("Employee Constructor Called...");
public String getName() {
public void setName(String name) {
this.name =
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
public boolean equals(Object obj) {
if (this == obj)
if (obj == null)
if (getClass() != obj.getClass())
Employee other = (Employee)
if (name == null) {
if (other.name != null)
} else if (!name.equals(other.name))
public String toString() {
return "Employee [name=" + name + "]";
public Object clone() {
Object obj =
obj = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
  下面的Java程序中,我们将用5种方式创建Employee对象。
public class ObjectCreation {
public static void main(String... args) throws Exception {
// By using new keyword
Employee emp1 = new Employee();
emp1.setName("Naresh");
System.out.println(emp1 + ", hashcode : " + emp1.hashCode());
// By using Class class's newInstance() method
Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee")
.newInstance();
// Or we can simply do this
// Employee emp2 = Employee.class.newInstance();
emp2.setName("Rishi");
System.out.println(emp2 + ", hashcode : " + emp2.hashCode());
// By using Constructor class's newInstance() method
Constructor&Employee& constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();
emp3.setName("Yogesh");
System.out.println(emp3 + ", hashcode : " + emp3.hashCode());
// By using clone() method
Employee emp4 = (Employee) emp3.clone();
emp4.setName("Atul");
System.out.println(emp4 + ", hashcode : " + emp4.hashCode());
// By using Deserialization
// Serialization
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.obj"));
out.writeObject(emp4);
out.close();
//Deserialization
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();
in.close();
emp5.setName("Akash");
System.out.println(emp5 + ", hashcode : " + emp5.hashCode());
  程序会输出:
Employee Constructor Called...
Employee [name=Naresh], hashcode : -
Employee Constructor Called...
Employee [name=Rishi], hashcode :
Employee Constructor Called...
Employee [name=Yogesh], hashcode : -
Employee [name=Atul], hashcode : 2051657
Employee [name=Akash], hashcode :
阅读(...) 评论()转载链接:http://blog.csdn.net/cws1214/article/details/
1、类的加载方式不同
& & 在执行Class.forName(&a.class.Name&)时,JVM会在classapth中去找对应的类并加载,这时JVM会执行该类的静态代码段。在使用newInstance()方法的时候,必须保证这个类已经加载并且已经连接了,而这可以通过Class的静态方法forName()来完成的。
& & 使用关键字new创建一个类的时候,这个类可以没有被加载,一般也不需要该类在classpath中设定,但可能需要通过classlaoder来加载。
2、所调用的构造方法不尽相同
& & new关键字能调用任何构造方法。
& & newInstance()只能调用无参构造方法。
3、执行效率不同
& & new关键字是强类型的,效率相对较高。
& & newInstance()是弱类型的,效率相对较低。
& & 既然使用newInstance()构造对象的地方通过new关键字也可以创建对象,为什么又会使用newInstance()来创建对象呢?
& & 假设定义了一个接口Door,开始的时候是用木门的,定义为一个类WoodenDoor,在程序里就要这样写 Door door = new WoodenDoor() 。假设后来生活条件提高,换为自动门了,定义一个类AutoDoor,这时程序就要改写为 Door door = new AutoDoor() 。虽然只是改个标识符,如果这样的语句特别多,改动还是挺大的。于是出现了工厂模式,所有Door的实例都由DoorFactory提供,这时换一种门的时候,只需要把工厂的生产模式改一下,还是要改一点代码。
& & 而如果使用newInstance(),则可以在不改变代码的情况下,换为另外一种Door。具体方法是把Door的具体实现类的类名放到配置文件中,通过newInstance()生成实例。这样,改变另外一种Door的时候,只改配置文件就可以了。示例代码如下:
String className = 从配置文件读取Door的具体实现类的类名;&
Door door = (Door) Class.forName(className).newInstance();
& & 再配合依赖注入的方法,就提高了软件的可伸缩性、可扩展性。
newInstance() 的参数版本与无参数版本详解
通过反射创建新的类示例,有两种方式:&
Class.newInstance()
Constructor.newInstance()
以下对两种调用方式给以比较说明:&
Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数;&
Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数。&
Class.newInstance() 抛出所有由被调用构造函数抛出的异常。&
Class.newInstance() 要求被调用的构造函数是可见的,也即必须是public类型的;&
Constructor.newInstance() 在特定的情况下,可以调用私有的构造函数。&
Class A(被调用的示例):&
Class B(调用者):
输入结果如下:&
通过Class.NewInstance()调用私有构造函数:&
通过Class.NewInstance()调用私有构造函数【失败】&
通过Constructor.newInstance()调用私有构造函数:&
A's constructor is called.&
说明方法newInstanceByClassNewInstance调用失败,而方法newInstanceByConstructorNewInstance则调用成功。&
如果被调用的类的构造函数为默认的构造函数,采用Class.newInstance()则是比较好的选择,&
一句代码就OK;如果需要调用类的带参构造函数、私有构造函数,&
就需要采用Constractor.newInstance(),两种情况视使用情况而定。&
不过Java Totorial中推荐采用Constractor.newInstance()。&
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:29863次
排名:千里之外
原创:32篇
转载:47篇
(6)(8)(5)(20)(6)(1)(4)(4)(4)(1)(1)(1)(1)(3)(2)(1)(1)(2)(4)(3)(1)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'String st = (String)Class.forName(&java.lang.String&).newInstance();
String st1=new String();
boolean bl=st.getClass()==st1.getClass();
System.out.println(bl);
返回为ture
这两种方法得到的结果是一样的
分析下原因,第一种方法是把new这个方式分解为两步,即首先调用Class加载方法加载某个类,然后实例化
可以分解开
Class cla=Class.forName(&java.lang.String&);//初始化
Object obj=cla.newInstance();//实例化为object类
String str=(String)//向下转换回子类
Class.forName()有它自己的用法
String str =&&;
Class c = Class.forName(str);
c.newInstance();
可以动态的创建对象
Object st = (String)Class.forName(&java.lang.String&).newInstance();
这个方法返回的是一个类,可以强制转换成各种子类
因此可以改变强制转换的类型与forName()的参数来创建不同类型的对象,只要他们是Object的子类
在连接数据库时,发现还可以这样用
Class.forName(driver);
查找资料了解到,这个方法在使用时,JVM会查找并加载指定的类,也就是说JVM会执行该类的静态代码段
而使用new时,这个类可以没有被加载(是可以不是一定)
测试使用Driver dri=new Driver();一样加载了类
然后测试了下构造方法的调用
class ceshi{
&& &int a=0;
&& &public ceshi(){
&& &&& &System.out.println(a);
&&&&& Class aaa=Class.forName(&ceshi&);//没有调用构造方法
&&&&& aaa.newInstance();//调用
&&&&& new ceshi();//调用
如果想要调用构造方法,需要调用newInstance
forname()会导致类被初始化,newInstance()才会实例化,而new()初始化+实例化
初始化和实例化的区别,另开一篇再做研究
相比较,new的语句简单,可以在创建时加入参数调用构造函数,而newInstance()把创建对象步骤分开,使得更灵活
本文已收录于以下专栏:
相关文章推荐
Class.forName()、newInstance() 、New 三者区别! 
        在Java开发特别是数据库开发中,经常会用到Class.forName( )这个方法。通过查询Ja...
在初始化一个类,生成一个实例的时候,newInstance()方法和new关键字除了一个是方法,一个是关键字外,最主要有什么区别?它们的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一...
在初始化一个类,生成一个实例的时候;newInstance() 和 new 有什么区别?
用newInstance与用new是区别的,区别在于创建对象的方式不一样,前者是使用类加载机制,那么为什么会...
new和newInstance的区别对比
在初始化一个类,生成一个实例的时候;newInstance() 和 new 有什么区别?
用newInstance与用new是区别的,区别在于创建对象的方式不一样,前者是使用类加载机制,那么为什么会...
在Java开发特别是数据库开发中,经常会用到Class.forName( )这个方法。通过查询Java Documentation我们会发现使用Class.forName( )静态方法的目的是为了动态...
转自:/mianshiti/it/java/7148/
在初始化一个类,生成一个实例的时候;newInstance() 和 new 有什么区别?
区别在于创建对象的方式不一样,前者是使用类加载机制,那么为什么会有两种创建对象方式?这个就要从可伸缩、可扩展,可重用等软件思想上解释了。Java中工厂模式经常使用newInstance来创建对象,因此...
在初始化一个类,生成一个实例的时候,newInstance()方法和new关键字除了一个是方法,一个是关键字外,最主要有什么区别?
       它们的区别在于创建对象的方式不一样,前者是使用类加载...
他的最新文章
讲师:刘文志
讲师:陈伟
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)}

我要回帖

更多关于 构造函数的实例 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信