反射

反射机制是Java大多数框架,尤其是用到了xml来配置相关信息的框架底层实现所必不可少的东西

个人认为反射机制是Java非常非常非常灵魂的东西

  1. 获取字节码文件(Class类对象)

    • 全限定名:
      Class clazz=Class.forname("全限定名");
      //返回一个Class对象(字节码文件)
      
    • 类名:
      Class clazz = 类名.class;
      //返回这个类的Class对象
      
    • 对象:
      Class clazz = 对象.getClass();
      //getClass()是Object的方法
      //返回此对象的直接类(即非父类)字节码
      
  2. 字节码创建对象

    • Class的方法:
      (强转)clazz.newInstance();
      //注!在jdk9以后不推荐newInstance(),使用下面这个
      (强转)clazz.getDeclaredConstructor().newInstance();
      //返回相应对象
      
    • 获取构造器来创建对象(不常用)
      因为构造器也是这个类的方法,那么毫无疑问反射可以直接用
      Constructor C = clazz.getConstructor(type.class);
      //type.class是构造器参数类型的字节码(如:String.class,Integer.class)(无参构造器则无参)
      C.newInstance();//返回对象
      
  3. 获取字段(以下代码均已获取字节码并创建了对象p)

    • 公共字段
      Field f = clazz.getField("字段名");
      f.set(p,[value]);//set方法
      
    • 私有字段
      Field f = clazz.getDeclaredField("字段名");//step1:暴力反射
      f.setAccessible(true);//step2:去除字段私有权限
      f.set(p,[value]);
      
  4. 获取方法

    • public
      Method m = clazz.getMethod("方法名");
      m.invoke([参数]);
      
    • private(和私有字段操作一样)
      Method m = clazz.getDeclaredMethod("方法名");
      m.setAccessible(true);//去除方法私有权限
      m.invoke([参数]);
      

      注:若方法有参数,则getMethod("方法名",[参数字节码])
      方法原型:getMethod/getDeclaredMethod (String methodname, Class... param)

  5. 绕过泛型检测

    ArrayList list = new ArrayList<>();
    list.add(1);
    Class clazz = Class.forName("java.util.ArrayList");//ArrayList的全限定名
    Method m = clazz.getMethod ("add",Object.class);
    m.invoke(list,"XXX");//直接字节码调用并声明函数
    

ps: this.getClass();//返回当前字节码(用于内类调用本类方法)

你可能感兴趣的:(反射)