1. 获取Class实例(运行时类)
public void test1() throws ClassNotFoundException {
//1.调用运行时类的静态属性:class
Class clazz1 = User.class;
System.out.println(clazz1);
//2. 调用运行时类的对象的getClass()
User u1 = new User();
Class clazz2 = u1.getClass();
//3. 调用Class的静态方法forName(String className)
String className = "com.hongshan.User"; //全类名
Class clazz3 = Class.forName(className);
System.out.println(clazz1 == clazz2);//true
System.out.println(clazz1 == clazz3);//true
//4. 使用类的加载器的方式 (了解)
Class clazz4 = ClassLoader.getSystemClassLoader().loadClass("com.hongshan.User");
System.out.println(clazz1 == clazz4);//true
}
上述四种方式中,第三种调用Class静态方法forName获取Class实例,一般在框架中运用得比较多,因为这种方法是动态获取实例的,不需要在编译阶段就定好具体哪一个类。第四种方式和第三种雷同。
2. 通过运行时类创建对象
通过反射创建对象,是通过第一章节中获取的Class实例(运行时类)来创建对象的。在java8及之前通过运行时类创建对象推荐调用Class实例的newInstance()方法。此方法需要满足以下条件方可使用:
条件1:要求运行时类中必须提供一个空参的构造器
条件2:要求提供的空参的构造器的权限要足够。
public void test1() throws InstantiationException, IllegalAccessException {
Class clazz = Person.class;
//创建Person类的实例
Person per = (Person) clazz.newInstance();
System.out.println(per);
}
}
由于上述方式创建运行时类对象受限于两个条件,在java8之后,推荐使用Class实例获取构造器,通过构造器返回一个运行时类的实例对象。
public void test2() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class clazz = Person.class;
//1.通过Class的实例调用getDeclaredConstructor(Class ... args),获取指定参数类型的构造器
Constructor constructor = clazz.getDeclaredConstructor();
//2.setAccessible(true):确保此构造器是可以访问的
constructor.setAccessible(true);
//3.通过Constructor实例调用newInstance(Object ... objs),返回一个运行时类的实例。
Person person = (Person) constructor.newInstance();
System.out.println(person);
}
3. 通过运行时类调用指定结构
3.1 调用指定的属性
public void test2() throws Exception {
Class clazz = Person.class;
//
Person per = (Person) clazz.newInstance();
//1.通过Class实例调用getDeclaredField(String fieldName),获取运行时类指定名的属性
Field nameField = clazz.getDeclaredField("name");
//2. setAccessible(true):确保此属性是可以访问的
nameField.setAccessible(true);
//3. 通过Filed类的实例调用get(Object obj) (获取的操作)
// 或 set(Object obj,Object value) (设置的操作)进行操作。
nameField.set(per,"Tom");
System.out.println(nameField.get(per));
}
步骤1.通过Class实例调用getDeclaredField(String fieldName),获取运行时类指定名的属性
步骤2. setAccessible(true):确保此属性是可以访问的
步骤3. 通过Filed类的实例调用get(Object obj) (获取的操作)或 set(Object obj,Object value) (设置的操作)进行操作。
3.2 调用指定的方法
public void test3() throws Exception {
Class clazz = Person.class;
Person per = (Person) clazz.newInstance();
//1.通过Class的实例调用getDeclaredMethod(String methodName,Class ... args),获取指定的方法
Method showNationMethod = clazz.getDeclaredMethod("showNation",String.class,int.class);
//2. setAccessible(true):确保此方法是可访问的
showNationMethod.setAccessible(true);
//3.通过Method实例调用invoke(Object obj,Object ... objs),即为对Method对应的方法的调用。
//invoke()的返回值即为Method对应的方法的返回值
//特别的:如果Method对应的方法的返回值类型为void,则invoke()返回值为null
Object returnValue = showNationMethod.invoke(per,"CHN",10);
System.out.println(returnValue);
}
步骤1.通过Class的实例调用getDeclaredMethod(String methodName,Class ... args),获取指定的方法
步骤2. setAccessible(true):确保此方法是可访问的
步骤3.通过Method实例调用invoke(Object obj,Object ... objs),即为对Method对应的方法的调用。
invoke()的返回值即为Method对应的方法的返回值
特别的:如果Method对应的方法的返回值类型为void,则invoke()返回值为null
3.3 调用指定的构造器
public void test4() throws Exception {
Class clazz = Person.class;
//1.通过Class的实例调用getDeclaredConstructor(Class ... args),获取指定参数类型的构造器
Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class);
//2.setAccessible(true):确保此构造器是可以访问的
constructor.setAccessible(true);
//3.通过Constructor实例调用newInstance(Object ... objs),返回一个运行时类的实例。
Person per = (Person) constructor.newInstance("Tom", 12);
System.out.println(per);
}
步骤1.通过Class的实例调用getDeclaredConstructor(Class ... args),获取指定参数类型的构造器
步骤2.setAccessible(true):确保此构造器是可以访问的
步骤3.通过Constructor实例调用newInstance(Object ... objs),返回一个运行时类的实例。