美文网首页
java反射知识点记录

java反射知识点记录

作者: 一二追 | 来源:发表于2021-10-26 17:52 被阅读0次

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

    相关文章

      网友评论

          本文标题:java反射知识点记录

          本文链接:https://www.haomeiwen.com/subject/iotyaltx.html