通过反射创建对应的运行时类的对象
方式一 :Class类的 newInstance():
newInstance():调用此方法,创建对应的运行时类的对象。内部调用了运行时类的空参的构造器。
@Test
public void test1() throws IllegalAccessException, InstantiationException {
Class<Person> clazz = Person.class;
Person obj = clazz.newInstance();
//Object obj = clazz.newInstance();
// Person p1=(Person)obj;
System.out.println(obj);
}
要想此方法正常的创建运行时类的对象,要求:
- 运行时类必须提供空参的构造器
- 空参的构造器的访问权限得够。通常,设置为public。
在javabean中要求提供一个public的空参构造器。原因:
- 便于通过反射,创建运行时类的对象
- 便于子类继承此运行时类时,默认调用super()时,保证父类有此构造器
方式二 :Class类的getConstructor((Class<?>… parameterTypes)
通过反射,先创建公共的构造器,再通过构造器获取运行时类对象
@Test
public void test2() throws Exception {
Class<Person> clazz = Person.class;
Constructor<Person> con = clazz.getConstructor(String.class, int.class);
Person p1 = con.newInstance("林莎", 28);
System.out.println(p1);
}
}
当然 你获取公共的无参的构造器 也是可以的 ,不过和方式一 :Class类的 newInstance():效果一样
方式三 :Class类的getDeclaredConstructor(Class<?>… parameterTypes)
可以调用一切情况的构造器,包括私有的构造器,暴力反射
@Test
public void test3() throws Exception {
Class<Person> clazz = Person.class;
Constructor<Person> con = clazz.getDeclaredConstructor(String.class);
con.setAccessible(true);
Person p1 = con.newInstance("煌煌");
System.out.println(p1);
}
反射的动态性
编译时并不能确定具体是要创建那个类的对象,只有运行时才能知道
@Test
public void test2(){
for(int i = 0;i < 10;i++){
int num = new Random().nextInt(3);//0,1,2
String classPath = "";
switch(num){
case 0:
classPath = "java.util.Date";
break;
case 1:
classPath = "java.lang.Object";
break;
case 2:
classPath = "com.cy.reflect.Person";
break;
}
try {
Object obj = getInstance(classPath);
System.out.println(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*
创建一个指定类的对象。
classPath:指定类的全类名
*/
public Object getInstance(String classPath) throws Exception {
Class clazz = Class.forName(classPath);
return clazz.newInstance();
}