java反射知识点记录

获取反射中的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 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调用日志
鸟吃虫子
鸟在树上睡觉

你可能感兴趣的:(java反射知识点记录)