反射机制 – Reflection

image-20230701003833109






Reflection API

  • Class

    image-20230701005825127

  • 通过反射获取类的Class对象

    Class c1 = Class.forName("com.chen.User");
    • 一个类在内存中只有一个Class对象
    • 一个类被加载后,类的整个结构都会被封装在Class对象中

image-20230701144644484

image-20230701145216220






获取Class类实例

public class reflection02 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
}
}

class Person{}

class Student extends Person{}

class Teacher extends Person{}

.class属性

image-20230701161447049

Class c = Student.class;



Class对象

image-20230702205627307

Class c1 = Object.class;    //类
Class c2 = Comparable.class; //接口
Class c3 = String[].class; //一维数组
Class c4 = int[][].class; //二维数组
Class c5 = Override.class; //注解
Class c6 = ElementType.class; //枚举
Class c7 = Integer.class; //基本数据类型
Class c8 = void.class; //void
Class c9 = Class.class; //Class



.getClass()方法

image-20230701161453859

Class c = person.getClass();



.forName()

image-20230701161500594

Class c = Class.forName("com.chen.Student");



Integer.Type

//基本内置类型的包装类都有一个Type属性
Class c = Integer.TYPE;



获取父类.getSuperclass()

//获取父类类型
Class c = c1.getSuperclass();






Java内存

image-20230702213823745



类加载内存分析

image-20230704234548987



类初始化

  • 发生初始化

    • new

    • 反射调用

      Class.forName("com.chen.Student");

image-20230704234716348



类加载器

image-20230705000335723

image-20230705130456225

获取类的运行时结构

Class c1 = Class.forName("com.chen.User");

获取类的名字

  • getName:获得包名+类名
  • getSimpleName:获得类名
//获取类的名字
c1.getName(); //获得包名+类名
c1.getSimpleName() //获得类名

获得类的属性

  • getFields : 只能获取public属性
  • getDeclaredFields:获取全部属性
Field[] fields = c1.getFields();

Field[] fields = c1.getDeclaredFields();

获得类的指定属性

  • getDeclaredField(属性名)
Field name = c1.getDeclaredField("name");

获得类的方法

  • getMethods:获得本类及其他父类的全部public方法
  • getDeclaredMethods:获得本类的所有方法
Method[] methods = c1.getMethods();   //获得本类及其他父类的全部public方法

Method[] methods = c1.getDeclaredMethods(); //获得本类的所有方法

获得类的指定方法

  • getMethod
Method getName = c1.getMethod("getName", null);

Method setName = c1.getMethod("setName", String.class);

获得构造器

  • getConstructors:获得public构造器
  • getDeclaredConstructors:获得全部构造器
Constructor[] constructors = c1.getConstructors();//获得public构造器

Constructor[] constructors= c1.getDeclaredConstructors();//获得全部构造器

获取指定构造器

  • getDeclaredConstructor:注意参数类型,否则实现重载
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);






动态创建对象执行方法

image-20230706012547036



Class对象

//获得class对象
Class c1 = Class.forName("com.chen.User");

创建类的对象

  • newInstance:构造对象(默认含有无参构造器)
//构造一个对象
User user = (User)c1.newInstance();//本质上调用无参构造器
  • 使用构造器创建对象
  • getDeclaredConstructor + newInstance
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);

User user2 = (User)constructor.newInstance("c",1,1);



调用指定方法

image-20230706012939770


通过反射调用方法

//通过反射调用方法
User user3 = (User) c1.newInstance();

//通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName", String.class);
  • invoke:激活

image-20230706013149861

//invoke:激活
//(对象,”方法的值“)
setName.invoke(user3,"辰呀");

通过反射操作属性

  • getDeclaredField(属性名)
//通过反射操作属性
User user4 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");

关闭程序的安全检查

image-20230706013640739

  • setAccessible
//不能直接操作私有属性,需要关闭程序的安全检查
name.setAccessible(true);//取消安全检查
name.set(user4,"彭呀");






性能监测

  • Sysem.currentTimeMills() 获取运行时间
long startTime = System.currentTimeMillis();
/*
逻辑代码
*/
long endTime = System.currentTimeMillis();

性能:普通(new)> 关闭性能检测的反射调用 > 反射调用






反射操作泛型

image-20230706140726625

//通过反射获取泛型
public class Test1 {

public void test01(Map<String,User> map, List<User> list){ }

public Map<String,User> test02(){
System.out.println("test02");
return null;
}

public static void main(String[] args) throws NoSuchMethodException {
//获取方法
Method method = Test1.class.getMethod("test01", Map.class, List.class);

//getGenericParameterTypes : 获得泛型的参数类型
Type[] genericParameterTypes = method.getGenericParameterTypes();

for (Type genericParameterType : genericParameterTypes) {

/*
输出结构为:
java.util.Map<java.lang.String, com.chen.User>
java.util.List<com.chen.User>
*/
//判断泛型的参数类型是否等于结构化的参数类型
//是结构化则解包
if (genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
/*
解包输出结构为:
class java.lang.String
class com.chen.User

class com.chen.User
*/
}
}
}



//查看返回值类型
method = Test1.class.getMethod("test02",null);
Type genericReturnType = method.getGenericReturnType();

/*
输出结构为:
java.util.Map<java.lang.String, com.chen.User>
*/


if (genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
/*
解包输出结构为:
class java.lang.String
class com.chen.User
*/
}
};

}
}






反射操作注解

//反射操作注解
public class Testc {

public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.chen.Student2");

//通过反射获取注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}

//获得注解的value的值
TableChen tableChen =(TableChen) c1.getAnnotation(TableChen.class);
String value = tableChen.value();
System.out.println(value);

//获得类指定的注解
Field f = c1.getDeclaredField("name");
FileChen annotation = f.getAnnotation(FileChen.class);

}

}

@TableChen("db_student")
class Student2{
@FileChen(columnName = "db_id",type = "int",length = 10)
private int id;
@FileChen(columnName = "db_id",type = "int",length = 10)
private int age;
@FileChen(columnName = "db_id",type = "varchar",length = 10)
private String name;

public Student2() {
}

public Student2(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "Student2{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableChen{
String value();
}

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FileChen{
String columnName();
String type();
int length();
}