- Reflection(反射)是被视为动态语言的关键 反射机运行在程序执行期借助于Reflection API取得任何类的内部信息 并能直接操作任意对象的内部属性及方法
- 加载完类后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象) 这个对象包含了完整的类的结构信息 我们可以通过这个对象看到类的结构
- 这个对象就像一面镜子 透过镜子看到类的结构 所以 我们形象的称之为:反射
- 什么时候应用反射?
- 在不确定要执行类的类型(对象)时 如浏览器向服务器发送请求 服务器根据浏览器请求 通过反射创建对应的对象. 进行处理
- 反射和封装性冲突吗?
- 不冲突
- 类加载过程
- 程序经过javac.exe命令后 会生成一个或多个字节码文件(.class文件) 接着我们用java.exe命令对某个字节码文件进行解释运行. 相当于将某个字节码文件加载到内存中. 此过程称为类加载
- 加载到内存中的类 称为运行时类
- Class类的实例就是一个运行时类
- 反射的常用方法 ```java
/**
@author:LYY 创建时间:2022/5/12 */ public class ReflectionTest {
/**
- 实例化Class的常用方法
注 四个class实例在内存中都是同一个 */ @Test void testOne() {
// 方式一 通过类.class Class
clazz1 = Person.class; // 方式二 通过对象的getClass方法 Person person = new Person(); Class clazz2 = person.getClass();
try {
// 方式三 通过Class静态方法
Class<?> clazz3 = Class.forName("com.atguigu.Person");
// 方式四 通过类加载器
ClassLoader classLoader = Person.class.getClassLoader();
Class<?> clazz4 = classLoader.loadClass("com.atguigu.Person");
// 获取当前类上的注解
Annotation[] annotations = clazz4.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
通过Class实例 创造运行时类实例 */ @Test void testInstance() { Class
personClass = Person.class; Person person = null; try { // 通过无参构造器创建运行时类对象
person = personClass.newInstance();
// 通过指定参数构造器 创建运行时类对象
Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor(String.class, Integer.class);
// 放开权限 保证私有的构造器也可以被调用
declaredConstructor.setAccessible(true);
Person person1 = declaredConstructor.newInstance("你好", 22);
System.out.println(person);
System.out.println(person1);
// 获取运行时类的所有构造器
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} System.out.println(“person = “ + person); }
/**
- 获取运行时类的所有属性
使用(赋值 输出)运行时类的属性 */ @Test void testField() { Class
personClass = Person.class; // 获取当前运行时类的所有public权限的属性,包含父类中定义的属性 Field[] fields = personClass.getFields(); // 获取当前运行时类的所有权限属性 不包含父类中的属性 Field[] declaredFields = personClass.getDeclaredFields(); for (Field f: declaredFields ) {
// 获取当前运行时类属性的权限修饰符
int modifiers = f.getModifiers();
System.out.print(Modifier.toString(modifiers)+"\t");
// 获取当前运行时类的数据类型
Class<?> type = f.getType();
System.out.print(type.getName() + "\t");
// 获取当前运行时类的属性的名称
System.out.println(f.getName());
}
try {
// 获取运行时类的指定属性 只能获取权限为public的属性
//Field name = personClass.getField("name");
// 没有public权限的name 结果为null
//System.out.println("name = " + name);
Field age = personClass.getDeclaredField("age");
// 开放权限 使私有属性可以被赋值
age.setAccessible(true);
// 给指定对象属性 赋值指定值
Person person = personClass.newInstance();
age.set(person, 45);
person.setName("草泥马");
System.out.println(person);
System.out.println();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} }
/**
获取当前运行时类的方法 */ @Test void testMethods() { Class
clazz = Person.class; // 返回当前运行时类的所有公共方法 包含父类方法 Method[] methods = clazz.getMethods(); for (int i = 0; i < methods.length; i++) { System.out.println(methods[i]);
} System.out.println(“*“); // 获取当前运行时类的所有方法 不包含父类 Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) {
// 获取当前前运行时类方法的权限修饰符
int modifiers = declaredMethod.getModifiers();
System.out.print(Modifier.toString(modifiers)+"\t");
// 获取当前运行时类方法的返回值类型
Type genericReturnType = declaredMethod.getGenericReturnType();
System.out.print(genericReturnType.getTypeName() + "\t");
// 获取当前运行时类的方法名称
String name = declaredMethod.getName();
System.out.print(name+"\t");
// 获取当前方法形参
Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
if (parameterTypes.length != 0) {
System.out.print("(");
for (Class<?> parameterType : parameterTypes) {
System.out.print(parameterType+"\t");
}
System.out.print(")");
}
/* Type[] genericParameterTypes = declaredMethod.getGenericParameterTypes();
System.out.println("-------------------");
if (genericParameterTypes.length != 0) {
for (Type genericParameterType : genericParameterTypes) {
System.out.println("+" + genericParameterType);
}
}*/
// 获取当前运行时类方法的返回值
Class<?> returnType = declaredMethod.getReturnType();
if (returnType != null) {
System.out.print(returnType.getName());
}
System.out.println();
}
try {
// 获取指定运行时类的方法
Method show = clazz.getDeclaredMethod("show");
show.setAccessible(true);
// 运行指定运行时类对象的show方法 无参方法
show.invoke(clazz.newInstance());
Method show1 = clazz.getDeclaredMethod("show", String.class);
// 释放权限 运行调用私有方法
show1.setAccessible(true);
show1.invoke(null, "CNM");
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} }
/**
- 获取运行时类的构造器
- 获取运行时类的父类
- 获取运行时类父类的泛型
- 获取运行时类的接口
获取运行时类所在的java包 */ @Test void testConstructors() { Class
personClass = Person.class; // 获取运行时类中所有公开的构造器 Constructor<?>[] constructors = personClass.getConstructors(); for (Constructor<?> constructor : constructors) { System.out.println(constructor);
} System.out.println(); // 获取当前运行时类中所有的构造器 Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors(); for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
System.out.println(); // 获取运行时类的父类 Type genericSuperclass = personClass.getGenericSuperclass(); System.out.println(genericSuperclass); // 获取运行时类的泛型 ParameterizedType parameterizedType = (ParameterizedType)genericSuperclass; Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); System.out.println(actualTypeArguments[0]); System.out.println(); // 获取运行时类的接口 Class<?>[] interfaces = personClass.getInterfaces(); System.out.println(interfaces[0]); // 可以显示接口中的泛型信息 前提时接口存在泛型 Type[] genericInterfaces = personClass.getGenericInterfaces(); System.out.println(genericInterfaces[0]); System.out.println(); // 获取运行时类所在的java包 Package aPackage = personClass.getPackage(); System.out.println(aPackage); } }
/**
@author LYY 自定义注解 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE,ElementType.FIELD}) @interface MyAnnotation {
String value() default “哈哈哈”; }
/**
- @author:LYY 创建时间:2022/5/12
*/
@MyAnnotation
class Person extends User
implements PersonTest{
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person() {
}
private Person(String name) {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public void show() {
System.out.println("测试一");
}
public int show(int a) {
return 1;
}
private static void show(String name) {
System.out.println("我时Person类中的私有方法!" + "形参是:" + name);
}
@Override
public void test01() {
System.out.println("接口中方法!");
}
}
/**
@author LYY 接口 */ interface PersonTest {
/**
- 无意义的方法 */ void test01(); }
/**
@author:LYY 创建时间:2022/5/12 person类父类 */ class User
implements Comparable{ private String userName; private int userAge;
public User() { }
public User(String userName, int userAge) {
this.userName = userName;
this.userAge = userAge;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getUserAge() {
return userAge;
}
public void setUserAge(int userAge) {
this.userAge = userAge;
}
private String eat(String eat) {
System.out.println("user类的eat方法!");
return eat;
}
public void hi() {
System.out.println("我是中国人!");
}
@Override public int compareTo(Object o) {
return 0;
} }
```