简介
Java反射是指在应用程序运行的时候动态的构造任意类的对象,可以了解任意一个类对象所属的类,可以了解任意一个类的
成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为java反射机制。
主要牵涉到的一个类叫Class类,该类代表普通类被加载到JVM中的字节码文件(.class)。
类加载器
类加载器ClassLoader,是将字节码文件加载到JVM中的一个东西。
例:Student类 ----javac编译—> Student.class ------ClassLoader------> JVM(OS)
类加载器的分类:
- BootStrapClassLoader 用于加载java的核心类库,如java.lang包下的String
- ExtensionClassLoader 用于加载java的拓展类库,如jre/lib/ext下的JAR文件,包括JDBC驱动程序,用于音频/图像处理的API等
- ApplicationClassLoader classpath下的类,即用户自定义的类
类加载器的双亲委派机制:
- 委托机制:
- 将加载一个类的请求交给父类加载器,如果这个父类加载器找不到要加载的类,那么子类再加载它
- 可见性机制:
- 子类的加载器可以看见所有的父类加载器加载的类,但是父类加载器看不到子类加载器加载的类
- 单一性机制:
- 加载一个类,仅加载一次,可以确保在委托机制中,如果父类加载器已经加载过这个类了,子类加载器不会再次加载
demo:Class类
只举例构造器,方法,字段(注意,不带declared的都包括父类中的成员(private类型的拿不到),带declared的是指声明在本类中的成员,private类型的都能拿到,静态/非静态的都是一起得到的)和泛型。
Teacher和Student类
@Data
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class Teacher {
public String name;
private Integer age;
private String gender;
private List<Student> students;
public Teacher(String name, Integer age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public void addAge(){
this.age++;
}
public static void teach(){
System.out.println("上课,同学们");
}
}
@Data
@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;
private Integer age;
private String gender;
}
public class ReflectTest {
public static void main(String[] args) {
Class<Teacher> teacherClass = Teacher.class;
/**
* 构造器
*/
System.out.println("------------------------构造器信息-----------------------------");
Constructor<?>[] declaredConstructors = teacherClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
//1.打印构造器信息,包括构造器和其参数
System.out.println(declaredConstructor.toString());
System.out.println();
//2.打印构造器的参数信息
Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println(parameterType);
}
System.out.println();
}
/**
* 成员方法/成员方法
*/
System.out.println("---------------------方法信息---------------------------------");
Method[] methods = teacherClass.getDeclaredMethods();
for (Method method : methods) {
Class<?>[] parameterTypes = method.getParameterTypes();
System.out.print(method.getName()+" : ");
for (Class<?> parameterType : parameterTypes) {
System.out.print(parameterType+",");
}
System.out.print("返回类型: "+method.getReturnType());
System.out.println();
}
/**
* 实例变量/静态变量
*/
System.out.println("-----------------------实例变量信息--------------------------------");
Field[] fields = teacherClass.getDeclaredFields();
for (Field field : fields) {
System.out.print(field.getType() + ": " + field.getName());
System.out.println();
}
System.out.println();
/**
* 泛型
*/
System.out.println("-----------------泛型----------------------------------");
try {
Field field = teacherClass.getDeclaredField("students");
System.out.println("得到students字段类型:"+field.getType());
Type genericType = field.getGenericType();
System.out.println("得到students字段带泛型的类型:"+genericType.getTypeName());
//判断这个类型是否是泛型
if (genericType instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType) genericType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
System.out.print("students字段真实类型:");
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
}
运行结果: