获取反射中的class对象
在反射中,要获取一个类或调用一个类的方法,首先需要获取到该类的class对象。
在java api中,获取class类对象有三种方法:
1.使用Class.forName静态方法。
说明:当你知道该类的全路径名时,你可以使用该方法获取Class类对象。
Class clz = Class.forName("java.lang.String");
2.使用.class方法
说明:这种方法只适合在编译前就知道操作的Class
Class clz = String.class
3.使用类对象的getClass()方法
String name="abc";
Class clz = name.getClass();
通过反射创建类对象
有两种方法:一种通过类对象的getInstance();另一种则是通过类对象的getConstructor的Constructor对象,调用constructor的getInstance()来创建类对象。
1.通过类对象的getInstance方法
Class clz = shopUser.getClass();
Class clz1 = ShopUser.class;
ShopUser user = clz.getInstance();
ShopUser user2 = clz1.getInstance();
2.通过constructor创建
ShopUser shopUser = shopUserService.get(shopUserRequest.getId());
try {
Constructor constructor = shopUser.getClass().getConstructor(String.class,Integer.class);
ShopUser shopUser1 = (ShopUser) constructor.newInstance("1",2);
} catch (Exception e) {
e.printStackTrace();
}
获取类名
String name = ShopUser.class.getName();
String simpleName = ShopUser.class.getSimpleName();
结果:
cn.enilu.flash.bean.entity.shop.ShopUser
ShopUser
获取类修饰符
int modifier = ShopUser.class.getModifiers();
System.out.println(modifier);
System.out.println(Modifier.isPublic(modifier));
结果:
1
true
获取包信息
String packageName = ShopUser.class.getPackage().getName();
System.out.println(packageName);
结果:
cn.enilu.flash.bean.entity.shop
获取父类
Class className = ShopUser.class.getSuperclass();
结果:
java.lang.Object
获取接口
说明:由于一个类可以实现多个接口,所以返回的结果为Class数组。注意getInterfaces()只返回指定类所实现的接口,不会返回父类所实现的接口。
Class[] class = ShopUser.class.getInterfaces();
获取构造函数
ShopUser.class.getConstructors();
如果你已经知道相关参数,可以通过
ShopUser.class.getConstructor("1","2");
获取构造函数的参数
Class[] parameterTypes = constructors.getParameterTypes();
获取method信息
Method[] methods = ShopUser.class.getDeclaredMethods();
Method[] methods2 = ShopUser.class.getMethods();
Method method =ShopUser.class.getDeclaredMethod("open",String.class,String.class,Integer.class);
获取或设置变量
Object value = fields3.get(shopUser);
fields3.set(shopUser, value);
调用method方法
method.invoke(shopUser,"name","mobile",23);
注意:invoke第一个参数为对象实例,后边的参数值
对于bean的getter和setter方法的判断
public static void testGettersSetters(Class aClass){
Method[] methods = aClass.getMethods();
for(Method method : methods){
if(isGetter(method)) System.out.println("getter: " + method);
if(isSetter(method)) System.out.println("setter: " + method);
}
}
public static boolean isGetter(Method method){
if(!method.getName().startsWith("get")) return false;
if(method.getParameterTypes().length != 0) return false;
if(void.class.equals(method.getReturnType()) return false;
return true;
}
public static boolean isSetter(Method method){
if(!method.getName().startsWith("set")) return false;
if(method.getParameterTypes().length != 1) return false;
return true;
}
访问类的注解信息
Annotation[] annotations = ShopUser.class.getAnnotations();
for (Annotation a :
annotations) {
System.out.println("name: " + a.toString());
if (a instanceof Entity){
Entity jsonIgnoreProperties = (Entity) a;
System.out.println(jsonIgnoreProperties.name());
}
}
结果:
t_shop_user
获取特定变量的注解信息
Field field = ...;
Annotation annotation = field.getAnnotation(Entity.class);
if(annotation instanceof MyAnnotation){
EntitymyAnnotation = (Entity) annotation;
System.out.println("name: " + myAnnotation.name());
}
同理获取方法的注解信息即以methd对象获取注解信息即可。
获取泛型方法或者泛型属性的返回类型,例如:List<String> userList
Method method = ...;
Type type = m.getGenericReturnType();
if (type instanceof ParameterizedType){
ParameterizedType type2 = (ParameterizedType) type;
Type[] typeArguments = type2.getActualTypeArguments();
for(Type typeArgument : typeArguments){
Class typeArgClass = (Class) typeArgument;
System.out.println("typeArgClass = " + typeArgClass);
}
}
结果:
java.lang.String
泛型参数同理。
动态代理部分
运行时创建接口的动态实现被称为动态代理。java.lang.reflect.Proxy提供了创建动态实现的功能。主要应用场景:方便地为某些行为添加一些共同的逻辑(Spring AOP(aspect oriented Programming))或者是将行为的执行完全交由代理控制(RPC远程过程调用(remote procedure call))
aop:我们就可以定义如下的一个切面和行为,然后在需要该功能的方法上增加相应注解即可,而不再需要每个方法单独写逻辑了,Spring AOP中大部分情况下都是给原执行逻辑添加一些东西。
rpc:RPC中的代理则是完全不需要原执行逻辑,而是完全地控制了行为的执行过程
public class MyInvocationHandler implements InvocationHandler {
private Object animal;
public MyInvocationHandler(Object m) {
animal = m;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("eat")) {
System.out.println("打印eat调用日志");
}
return method.invoke(animal, args);
}
}
Animal animal = new Bird();
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(animal);
Animal animalPlugin = (Animal) Proxy.newProxyInstance(animal.getClass().getClassLoader(), animal.getClass().getInterfaces(), myInvocationHandler);
animalPlugin.eat();
animalPlugin.sleep();
结果:
打印eat调用日志
鸟吃虫子
鸟在树上睡觉
网友评论