访问类所有变量注解信息:
Field field = ... //obtain field object Annotation[] annotations = field.getDeclaredAnnotations(); for(Annotation annotation : annotations){ if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("name: " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value()); } }访问类某个特定变量的注解信息:
Field field = ... // obtain method object Annotation annotation = field.getAnnotation(MyAnnotation.class); if(annotation instanceof MyAnnotation){ MyAnnotation myAnnotation = (MyAnnotation) annotation; System.out.println("name: " + myAnnotation.name()); System.out.println("value: " + myAnnotation.value()); }获取泛型信息
很多人认为java类在编译的时候会把泛型信息给擦除掉,所以在运行时是无法获取到泛型信息的。其实在某些情况下,还是可以通过反射在运行时获取到泛型信息的。
获取到java.lang.reflect.Method对象,就有可能获取到某个方法的泛型返回信息。
泛型方法返回类型
下面的类中定义了一个返回值中有泛型的方法:
下面的代码使用反射检测getStringList()方法返回的是List<String>而不是List
Method method = MyClass.class.getMethod("getStringList", null); Type returnType = method.getGenericReturnType(); if(returnType instanceof ParameterizedType){ ParameterizedType type = (ParameterizedType) returnType; Type[] typeArguments = type.getActualTypeArguments(); for(Type typeArgument : typeArguments){ Class typeArgClass = (Class) typeArgument; System.out.println("typeArgClass = " + typeArgClass); } }上面这段代码会打印:typeArgClass = java.lang.String
泛型方法参数类型
下面的类定义了一个有泛型参数的方法setStringList():
Method类提供了getGenericParameterTypes()方法获取方法的泛型参数。
method = Myclass.class.getMethod("setStringList", List.class); Type[] genericParameterTypes = method.getGenericParameterTypes(); for(Type genericParameterType : genericParameterTypes){ if(genericParameterType instanceof ParameterizedType){ ParameterizedType aType = (ParameterizedType) genericParameterType; Type[] parameterArgTypes = aType.getActualTypeArguments(); for(Type parameterArgType : parameterArgTypes){ Class parameterArgClass = (Class) parameterArgType; System.out.println("parameterArgClass = " + parameterArgClass); } } }上面的代码会打印出parameterArgType = java.lang.String
泛型变量类型
通过反射也可以获取到类的成员泛型变量信息——静态变量或实例变量。下面的类定义了一个泛型变量:
通过反射的Filed对象获取到泛型变量的类型信息:
Field field = MyClass.class.getField("stringList"); Type genericFieldType = field.getGenericType(); if(genericFieldType instanceof ParameterizedType){ ParameterizedType aType = (ParameterizedType) genericFieldType; Type[] fieldArgTypes = aType.getActualTypeArguments(); for(Type fieldArgType : fieldArgTypes){ Class fieldArgClass = (Class) fieldArgType; System.out.println("fieldArgClass = " + fieldArgClass); } }Field对象提供了getGenericType()方法获取到泛型变量。
上面的代码会打印出:fieldArgClass = java.lang.String
动态代理
使用反射可以在运行时创建接口的动态实现,java.lang.reflect.Proxy类提供了创建动态实现的功能。我们把运行时创建接口的动态实现称为动态代理。
动态代理可以用于许多不同的目的,例如数据库连接和事务管理、用于单元测试的动态模拟对象以及其他类似aop的方法拦截等。
创建代理
调用java.lang.reflect.Proxy类的newProxyInstance()方法就可以常见动态代理,newProxyInstance()方法有三个参数:
1、用于“加载”动态代理类的类加载器。
2、要实现的接口数组。
3、将代理上的所有方法调用转发到InvocationHandler的对象。
代码如下:
运行上面代码后,proxy变量包含了MyInterface接口的动态实现。
对代理的所有调用都将由到实现了InvocationHandler接口的handler 对象来处理。