JAVA反射

1、概述
  • JAVA反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法

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

  • 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

  • 动态获取类中信息,就是java反射 。可以理解为对类的解剖。

  • 要想要对字节码文件进行解剖,必须要有字节码文件对象,如何获取字节码文件对象呢?

2、获取字节码对象的方式
  • 1、Object类中的getClass()方法的。想要用这种方式,必须要明确具体的类,并创建对象(麻烦)。

    String str = new String();
    Class clazz = str.getClass();
    
    String str1 = new String();
    Class clazz1 = str1.getClass();
    System.out.println(clazz == clazz1); //true
    
  • 2、任何数据类型都具备一个静态的属性.class来获取其对应的Class对象。相对简单,但是还是要明确用到类中的静态成员(还是不够扩展)。

    Class clazz = String.class;
    Class clazz1 = String.class;
    System.out.println(clazz == clazz1); // true
    
  • 3、只要通过给定的类的 字符串名称就可以获取该类,更为扩展。可是用Class类中的方法完成。该方法就是forName。这种方式只要有名称即可,更为方便,扩展性更强。

    String className = "cn.itcast.bean.Person";
    Class clazz = Class.forName(className);
    System.out.println(clazz);
    
3、早期创建对象和反射创建对象流程的区别
  • 早期:new时候,先根据被new的类的名称找寻该类的字节码文件,并加载进内存,并创建该字节码文件对象,并接着创建该字节文件的对应的Person对象。

  • 反射:根据类名称找寻该名称类文件,并加载进内存,并产生Class对象,通过newInstance创建对象。

    String name = "cn.itcast.bean.Person";
    Class clazz = Class.forName(name);
    Object obj  = clazz.newInstance();
    
  • 当获取指定名称对应类中的所体现的对象时,而该对象初始化不使用空参数构造该怎么办呢?既然是通过指定的构造函数进行对象的初始化,所以应该先获取到该构造函数。通过字节码文件对象即可完成。该方法是:getConstructor(paramterTypes);

    String name = "cn.itcast.bean.Person";
    Class clazz = Class.forName(name);
    
    //获取到了指定的构造函数对象。
    Constructor constructor = clazz.getConstructor(String.class,int.class);
    
    //通过该构造器对象的newInstance方法进行对象的初始化。
    Object obj = constructor.newInstance("小明", 38);
    
4、获取字节码文件中的字段
  • 获取类中所有的字段或指定字段对象(只获取pulic的字段)

    Class<String> clazz = String.class;
    Field[] fields = clazz.getFields();
    
    // 因为value是私有字段,所以获取时会抛NoSuchFieldException异常
    Field field = clazz.getField("value");
    
  • 获取所有的字段(可包含private)

    Class<String> clazz = String.class;
    Field[] fields = clazz.getDeclaredFields();
    
    Field field = clazz.getDeclaredField("value");
    
  • 给对象的字段赋值

    Class<String> clazz = String.class;
    Object obj = clazz.newInstance();
    Field field = clazz.getDeclaredField("value");
    char[] value = { '2', '3' };
    
    // value的值赋为23,此时会报错,因为value是私有的
    field.set(obj, value);
    
    // 暴力对私有字段的访问取消权限检查,此时就可以正常赋值了
    field.setAccessible(true);
    field.set(obj, value);
    
    
5、操作Class中的函数
  • 获取Method对象

    Class<String> clazz = String.class;
    
    // 获取的都是公有的方法。
    Method[] methods1 = clazz.getMethods();
    
    // 只获取本类中所有方法,包含私有。
    Method[] methods2 = clazz.getDeclaredMethods();
    
    // 根据名称获取指定方法(空参)
    Method method = clazz.getMethod("show", null);  
    // 方法是私有的话会抛NoSuchMethodException异常
    // Method method = clazz.getDeclaredMethod("show", null);
    
    // 根据名称获取指定方法(带参)
    Method method = clazz.getMethod("paramMethod", String.class, int.class);
    
  • 方法的调用

    Class clazz = Class.forName("cn.itcast.bean.Person");
    Method method = clazz.getMethod("paramMethod", String.class,int.class);
    
    Object obj = clazz.newInstance();
    method.invoke(obj, "小强",89);
    // 空参函数的调用:method.invoke(obj, null);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值