前言
Java 反射解析
补充一手和反射有关的知识点,随缘更新
一、通过反射越过泛型检查
Java为了向下兼容,提出来的泛型只是一个语法糖,并不是真正的泛型,通过反射,我们可以越过泛型检查。
因为在编译时期Vava会对泛型进行检查。但是当类被转化为字节码文件( .class)时候(运行时期,没有泛型),泛型就被擦除了,也就没有了泛型检查。
代码实现
public static void main(String[] args) throws Exception, Exception {
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
System.out.println(arrayList); // 输出: [1, 2, 3]
Class clazz = arrayList.getClass();
Method m = clazz.getMethod("add",Object.class );
m.invoke(arrayList, "String");
System.out.println("反射后的结果:"+arrayList); //输出: 反射后的结果:[1, 2, 3, String]
}
}
但是不能使用get,通过反射添加的数据会因为无法通过其强制类型转换而报错
public class TT {
public static void main(String[] args) throws Exception{
Map<String, String> map = new HashMap<>();
String key = "key";
Integer val = Integer.valueOf(1);
Method m = HashMap.class.getDeclaredMethod("put", new Class[]{Object.class, Object.class});
m.invoke(map, key, val);
System.out.println(map);
//但是下面的输出会报错
System.out.println(map.get(key));
}
}
控制台报错:
{key=1}
Exception in thread "main" java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of loader 'bootstrap')
at TT.main(TT.java:26)
二、反射+注解控制执行main类
代码实现
反射类
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@Pro(className = "ReflectTest", methodName = "main")
public class Test {
public static void main(String[] args) throws Exception {
//1.通过当前类的字节码对象,判断当前类上是否有自定义的Pro注解
Class reflectTestClass = Test.class;
//2.有的话,获取该自定义注解,并生成对象
if (reflectTestClass.isAnnotationPresent(Pro.class)) {
Annotation annotation = reflectTestClass.getAnnotation(Pro.class);
Pro pro = (Pro) annotation;// 自定义注解都继承自父接口Annotation,用多态的方式获得Annotation对象后,需要向下转型为自定义的注解类型Pro的对象
//3.通过该注解对象,获取注解的内容className和methodName
String className = pro.className();
String methodName = pro.methodName();
//4.根据全类名className获取对应类字节码对象
Class clazz = Class.forName(className);
//5.根据该字节码对象获取指定方法methodName的Method对象
Method method = clazz.getMethod(methodName, String[].class);
//6.通过Method对象执行该方法
method.invoke(clazz.newInstance(), (Object) new String[5]);
}
}
}
注解类
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Pro {
String className();
String methodName();
}
实验类
public class ReflectTest {
public static void main(String[] args) {
System.out.println("调用ReflectTest类main方法");
}
}