1. 反射的理解
我们平常创建对象、调用属性和方法的方式:
Person person = new Person();
person.name = "jixian";
person.hello();
使用反射实现相同的效果:
//创建对象
Class<Person> clazz = Person.class;
Person person = clazz.newInstance();
//设置属性
Field name = clazz.getField("name");
name.set(person, "jixian");
//调用方法
Method hello = clazz.getMethod("hello");
hello.invoke(person);
2. 获取Class实例的四种方式
所有Java类型都可以有Class实例。
//方式一:直接通过类名.class
Class clazz1 = Person.class;
//方式二:通过对象调getClass()
Person person = new Person();
Class clazz2 = person.getClass();
//方式三:Class.forName()
Class clazz3 = Class.forName("com.jixian.practice06.Person");
//方式四:通过类加载器
Class clazz4 = ClassLoader.getSystemClassLoader().loadClass("com.jixian.practice06.Person");
3. 反射的应用
3.1 创建运行时类的对象
在JDK8版本下,通过Class的实例调用newinstance( ),但是必须提供一个空参构造器,空参构造器的权限也需要足够。
Class<Person> aClass = Person.class;
Person person = aClass.newInstance();
在JDK9以后,需要用Constructor类的newinstance( )进行创建对象。
Class<Person> aClass = Person.class;
Constructor<Person> constructor = aClass.getConstructor();
Person person = constructor.newInstance();
拓展
JavaBean中,要求给当前类提供一个公共的空参构造器,有什么用?
- 子类对象在实例化时,子类构造器首行默认调用父类的空参构造器。
- 在反射中,经常用来创建运行时类的对象。
3.2 获取运行时类的完整结构
getFields()获取运行时类本身及其父类中声明为public的属性。
Field[] fields = aClass.getFields();
getDeclaredFields()获取当前运行时类中声明的所有属性。
Field[] declaredFields = aClass.getDeclaredFields();
getType()获取属性的类型。
Class aClass = Person.class;
Field field = aClass.getField("name");
System.out.println(field.getType());
getModifiers()获取属性的修饰符。
Field field = aClass.getField("name");
int modifiers = field.getModifiers();
System.out.println(modifiers + ":" + Modifier.toString(modifiers));
getPackage()获取运行时类所在的包。
Package aPackage = aClass.getPackage();
System.out.println(aPackage.getName());
getInterfaces()获取类实现的接口。
Class[] interfaces = aClass.getInterfaces();
for (Class c: interfaces){
System.out.println(c);
}
getSuperclass()获取运行时类的父类。
Class superclass = aClass.getSuperclass();
System.out.println(superclass);
getGenericSuperclass()获取带泛型的父类。
Type genericSuperclass = clazz.getGenericSuperclass();
System.out.println(genericSuperclass);
获取父类的泛型。
Type genericSuperclass = clazz.getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
Type[] arguments = parameterizedType.getActualTypeArguments();
System.out.println(((Class)arguments[0]).getName());