• Java中的反射


    一,什么是反射

    1,反射机制是在 运行状态 中:

    对于任意一个类,都能知道这个类的所有属性和方法

    对于任意一个对象,都能够调用它的任意一个方法和属性。

    2,反射提供的功能:

    在运行时判断任意一个对象所属的类

    在运行时构造任意一个类的对象

    在运行时判断任意一个类所具有的成员变量和方法

    在运行时调用任意一个对象的方法

    生成动态代理(动态代理底层用到了反射)

    二,反射入口

    1,获取反射对象(反射入口):就是拿到Class。有三种方法:

    1.1,Class.forName("全类名");需要 包名+类名。需要处理异常

      Class<?> perClazz = Class.forName("sys.person");//推荐这种方式

      System.out.println(perClazz);

    1.2,类名.class

      Class<?> perClazz = Person.class;

      System.out.println(perClazz);

    1.3,对象.getClass();

      Person per = new Person();

      Class<?> perClazz = per.getClass(); //getClass()方法是object提供的

      System.out.println(perClazz);

    2,获取公共的方法

      Class<?> perClazz = Class.forName("sys.person");

      Method[] methods = perClazz.getMethods();

      for(Method method : methods){

        System.out.print(method);

      }

    打印结果:

    public static void sys.Person.staticMethod()

    pulic java.lang.String sys.Person.getName()

    public final native void java.lang.Object.hashCode()

    可以获取本类和父类(Object)中的public方法。

    3,获取接口(多实现)

      Class<?> perClazz = Class.forName("sys.person");

      Class<?>[]  interfaces = perClazz.getInterface();

      for(Class<?> inter : interfaces){

        System.out.println(inter)

      }

    打印结果(Person实现两个MyInterface,MyInterface2):

    interface sys.MyInterface

    interface sys.MyInterface2

    4,获取所有父类(单继承)

      Class<?> perClazz = Class.forName("sys.person");  

      Class<?>  superClass= perClazz.getInterface();

      System.out.println(superClass);

    打印结果:

    class java.lang.Object

    5,获取所有的构造方法

      Class<?> perClazz = Class.forName("sys.person");  

      Constructor<?>[] constructors = perClazz.getConstructors();

      for(Constructor constructor : constructors){

        System.out.println(constructor);

      }

    打印结果:

    public sys.Person(int,java.lang.String);//两个参数

    public sys.Person(int);//一个参数

    public sys.Person();//无参

    6,获取所有的公共属性

      Class<?> perClazz = Class.forName("sys.person");

      Field[] fields = perClazz.getFields();

      for(Field field : fields){

        System.out.println(field);

      }

    打印结果:

    什么也没有,因为Person里定义的变量都是private的。

    如果定义了public变量(public String title),反射才能获取到(public java.lang.String sys.Person.title)。

    7,获取当前类的所有方法(要求:只能是当前类,并忽略访问修饰符限制)

      Class<?> perClazz = Class.forName("sys.person");

      Method[] declaredMethods = perClazz.getDeclaredMethods();

      for(Method method : declaredMethods){

        System.out.print(method);

      }

    打印结果:

    public java.lang.String sys.Person.getName()

    private void sys.Person.privateMethod()

    public static void sys.Person.staticMethod()

    8,获取所有的属性(当前类,忽略访问修饰符)

      Class<?> perClazz = Class.forName("sys.person");

      Field[] fields = perClazz.getDeclaredFields();

      for(Field field : fields){

        System.out.println(field);

      }

    打印结果:

    private int sys.Person.id

    private java.lang.String sys.Person.name

    public java.lang.String sys.Person.title

     9,获取当前反射所代表类(接口)的对象

      Class<?> perClazz = Class.forName("sys.person");

      Object instance = perClazz.newInstance();

      Person per = (Person)instance;//强转

      per.interfaceMehthod();//调用方法

    如果调用成功,说明instance就是Person对象

    三,通过反射获取对象的实例,并操作对象

      Class<?> perClazz = Class.forName("sys.person");

      Person per = (Person)perClazz.newInstance();

      per.setId(1);

      per.setAge(22);

      System.out.println(per.getId() + " : "+ per.getAge());

    可以打印出 id 和 age

    四,通过反射获取对象的实例,操作属性

      Class<?> perClazz = Class.forName("sys.person");

      Person per = (Person)perClazz.newInstance();

      Field idField = perClazz.getDeclaredField(" id ");

      //现在要访问的是private修饰的id,但是private是私有的(私有的只能通过 public void setId()来访问),

      //但是我们通过反射还是想访问private int id 。所以,我们在操作属性之前,需要修改属性访问权限。

      //使用反射时,如果因为访问修饰符限制造成异常,可以通过setAccessible(true)来解决,同理操作私有方法也可以这样做

      idField.setAccessible(true);

      idField.set(per,1); // 相当于 ----->per.setId(1);

      System.out.println( per.getId() );

    五,通过反射获取对象的实例,操作方法

      Class<?> perClazz = Class.forName("sys.person");

      Person per = (Person)perClazz.newInstance();

    1,无参方法

      Method method = perClazz.getDeclaredMethod(" privateMethod ",null);//方法名:privateMethod,参数:null

      //操作方法私有方法时,把访问修饰符屏蔽掉

      method.setAccessible(true);

      method.invoke(per,null);//方法的调用:invoke

    2,有参方法

      Method method2 = perClazz.getDeclaredMethod(" privateMethod2 ",String.class);//方法名:privateMethod2,参数:String类型

      method2.setAccessible(true);

      method2.invoke(per," 张三 ");//调用方法,并传参数

    六,通过反射获取对象的实例,操作构造方法

    1,获取本类全部构造方法(公有的,私有的构造方法都能拿到)

      Class<?> perClazz = Class.forName("sys.person");  

      Constructor<?>[] constructors = perClazz.getDeclaredConstructors();

      for(Constructor constructor : constructors){

        System.out.println(constructor);

      }

    2,获取指定的构造方法(比如:public Person(int id){ this.id = id })

      Class<?> perClazz = Class.forName("sys.person");  

      Constructor<?> constructor = perClazz.getConstructor(int.class);

      System.out.println(constructor);

    打印结果:

    public sys.Person(int);

    3,获取私有的构造方法

    ----->通过getDeclaredConstructor();获取。注意使用setAccessible(true)

    七,

      

      

      

      

      

  • 相关阅读:
    JS和C# 里的闭包及闭包在事件中的使用
    ***项目开发记录
    七牛云存储之应用视频上传系统开心得
    二维码及二维码接合短URL的应用
    EF批量添加,删除,修改的扩展
    ngTemplateOutlet递归的问题
    每日新知2019-06-03
    Spring boot初始
    纯前端播放本地音乐
    macbook 安装任意来源
  • 原文地址:https://www.cnblogs.com/inspred/p/10817134.html
Copyright © 2020-2023  润新知