Java反射使用总结 (4)

访问类所有变量注解信息:

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对象,就有可能获取到某个方法的泛型返回信息。

泛型方法返回类型
下面的类中定义了一个返回值中有泛型的方法:

public class MyClass { protected List<String> stringList = ...; public List<String> getStringList(){ return this.stringList; } }

下面的代码使用反射检测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():

public class MyClass { protected List<String> stringList = ...; public void setStringList(List<String> list){ this.stringList = list; } }

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

泛型变量类型
通过反射也可以获取到类的成员泛型变量信息——静态变量或实例变量。下面的类定义了一个泛型变量:

public class MyClass { public List<String> stringList = ...; }

通过反射的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的对象。
代码如下:

InvocationHandler handler = new MyInvocationHandler(); MyInterface proxy = (MyInterface) Proxy.newProxyInstance( MyInterface.class.getClassLoader(), new Class[] { MyInterface.class }, handler);

运行上面代码后,proxy变量包含了MyInterface接口的动态实现。

对代理的所有调用都将由到实现了InvocationHandler接口的handler 对象来处理。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfsjp.html