Class主要是反射的源头,不光可以取得对象所在类的信息,也可以通过Class类的方法进行对象的实例化操作,正常情况下,使用new关键字为对象实例化,如果现在已经实例化好了class对象,则就可以通过Class类中提供的newInstance()方法。
public T newInstance()throws InstantiationException, IllegalAccessException
package com.testClass;
class Person{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "姓名:"+this.name+",年龄:"+this.age;
}
}
public class InstanceDemo01 {
public static void main(String args[]){
Class> c = null;//声明class对象
try {
c= Class.forName("com.testClass.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Person per =null;
try {
per = (Person) c.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
per.setName("张三");
per.setAge(20);
System.out.println(per);
}
}
输出结果:
姓名:张三,年龄:20
通过以上代码,可以发现,即使不使用关键字new对象也可以进行实例化操作,但是,在使用以上操作的时候有一点要注意,在操作类中必须存在无参构造方法,否则无法实例化。
package com.testClass;
class Person{
private String name;
private int age;
public Person(String name,int age){
this.setName(name);
this.setAge(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "姓名:"+this.name+",年龄:"+this.age;
}
}
public class InstanceDemo01 {
public static void main(String args[]){
Class> c = null;//声明class对象
try {
c= Class.forName("com.testClass.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Person per =null;
try {
per = (Person) c.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
per.setName("张三");
per.setAge(20);
System.out.println(per);
}
}
输出结果:
java.lang.InstantiationException: com.testClass.Person
at java.lang.Class.newInstance(Class.java:364)
at com.testClass.InstanceDemo01.main(InstanceDemo01.java:42)
Exception in thread "main" java.lang.NullPointerException
at com.testClass.InstanceDemo01.main(InstanceDemo01.java:48)
使用以上的方式实际上还是需要类中构造方法的支持,符合于对象的实例化要求。如果要想解决这样的问题,则必须明确的指定要调用的构造方法,并传递参数,但是从实际的开发角度讲,一般使用反射实例化对象的时候,类中都最好存在一个无参构造,这样的操作比较合理。
如果要想调用有参,则必须按照以下的步骤进行:
在Constructor类中存在一个方法:
public T newInstance(Object... initargs)
throws InstantiationException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
传递初始化参数,以进行对象的实例化操作。
package com.testClass;
import java.lang.reflect.Constructor;
class Person{
private String name;
private int age;
public Person(String name,int age){
this.setName(name);
this.setAge(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "姓名:"+this.name+",年龄:"+this.age;
}
}
public class InstanceDemo01 {
public static void main(String args[]){
Class> c = null;//声明class对象
try {
c= Class.forName("com.testClass.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Person per =null;
Constructor> constructor[]=null;
constructor=c.getConstructors();
try {
per = (Person)constructor[0].newInstance("张三",18);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(per);
}
}
输出结果:
姓名:张三,年龄:18
但是,从实际角度看,如果要使用反射进行对象的实例化操作,最好在类中存在无参构造。
总结:
在使用Class实例化对象的时候必须保证类中存在一个无参构造,否则无法使用。
如果要想调用有参构造进行对象的实例化操作,则必须使用constructor类完成,此类表示构造方法,并通过可变参数传递要求的内容。