反射的应用
注:clazz是Class的实例,per才是Person的对象!!!
创建运行时类的对象
通过Class实例调用newInstance()方法
条件1:要求运行时类中必须提供一个空参的构造器
条件2:要求提供的空参的构造器的权限要足够
在JDK9后此方法被标记为过时,替换为:Constructor调用newInstance()
获取运行时类的内部结构:所有属性、所有方法、所有构造器
getFields():获取到运行时类本身及其所有父类中声明为public权限的属性
getDeclaredFields():获取当前运行时类中声明的所有属性
getMethods():获取到运行时类本身及其所有父类中声明为public权限的方法
getDeclaredMethods():获取当前运行时类中声明的所有方法
获取运行时类的内部结构:父类、接口们、包、带泛型的父类、父类的泛型等
- getSuperclass():获取运行时类的父类
- getInterfaces():获取运行时类的接口,因接口数量不唯一,需用数组接收,循环遍历
- getPackage():获取运行时类的包
- getGennericSuperclass():获取运行时类的带泛型的父类
- 获取运行时类的父类的泛型:此代码为工具代码,用时粘贴就行
1 2 3 4 5 6 7 8 9 10 11
| Class<?> clazz = Class.forName("Person");
Type genericSuperclass = clazz.getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); }
|
调用指定的属性*
先指定一个Person类,类中要有一个空参public构造器,方便newInstance()方法生成Person的对象per``
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Person { private String name; public int age; private Person(String name, int age) { this.name = name; this.age = age; } public Person() { System.out.println("person()"); } private void show(int age, String name){ System.out.println("这是show方法"); System.out.println(age + name); } }
|
关于属性的调用:get/set方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import org.junit.Test;
import java.lang.reflect.Field;
public class reflectTest { @Test public void test() throws Exception { Class<Person> clazz = Person.class; Person per = clazz.newInstance(); Field field = clazz.getField("age"); field.setInt(per,18); System.out.println(field.get(per)); Field field1 = clazz.getDeclaredField("name"); field1.setAccessible(true); field1.set(per,"XIAOBAI"); System.out.println(field1.get(per)); } }
|
关于方法的调用:invoke方法
1 2 3 4 5 6 7 8 9
| @Test public void test1() throws Exception { Class<Person> clazz = Person.class; Person per = clazz.newInstance(); Method method = clazz.getDeclaredMethod("show", int.class, String.class); method.setAccessible(true); Object invoke = method.invoke(per, 22,"Xiaobai"); }
|
注:invoke方法的返回值即为调用方法的返回值,如果是void方法则会返回null
调用静态属性的时候,不需要对象per去调用,使用Clazz实例clazz或Person.class(指代此类)去调用即可
1 2 3 4 5 6 7 8
| public void test() throws Exception { Class<Person> clazz = Person.class; Field field1 = clazz.getDeclaredField("name"); field1.setAccessible(true); field1.set(Person.class,"XIAOBAI"); System.out.println(field1.get(Person.class));
|
调用静态属性的时候,不需要对象per去调用,使用Clazz实例clazz或Person.class(指代此类)或null去调用即可
1 2 3 4 5 6 7 8 9 10
| @Test public void test1() throws Exception { Class<Person> clazz = Person.class; Person per = clazz.newInstance(); Method method = clazz.getDeclaredMethod("show", int.class, String.class); method.setAccessible(true); Object invoke = method.invoke(null, 22,"Xiaobai"); }
|
调用构造器,和调用方法的区别是不需要写入方法名
1 2 3 4 5 6 7 8 9
| @Test public void test2() throws Exception { Class<Person> clazz = Person.class; Constructor<Person> constructor = clazz.getDeclaredConstructor(String.class, int.class); constructor.setAccessible(true); Person per = constructor.newInstance("XIAOBAI", 18); }
|
对比通过Class实例调用newInstance()方法,使用Constructor调用newInstance()创建实例的方法,因为constructor.setAccessible(true);语句的原因,所以不要求构造器public,因为后面也可以写入形参,所以不要求构造器空参