JAVA基础——反射详解

1.什么是反射( reflect

JAVA反射机制是运行状态中,对于任意一个类都能够知道这个类的所有属性个方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息及动态调用对象的方法的功能称为java语言的反射机制。

简单说:在运行状态下,通过class文件对象,去使用构造方法,成员变量和成员方法

注意:在反射中包含Declared的方法表示获取私有的成员内容,一般结合setAccessible(true)方法一起使用

2.创建Class文件的三种方式

Class.forName("类全名");

对象名.getClass(); 

类名.class

推荐使用:Class.forName("类全名");

3.获取构造方法并创建对象

概述:
        java.lang.reflect.Constructor:构造方法管理器,通过该对象的newInstance方法能有创建构造方法
步骤
1、获取Class对象
2、通过调用getDeclaredConstructor或者getConstructor 方法创建构造器(Constructor)对象,如果构造方法没有形式参数写null
      public Constructor  getDeclaredConstructor(形式参数1对应的.class对象, 形式参数2对应的.class对象....):该方法可以获取私有构造方法
      public Constructor  getConstructor(形式参数1对应的.class对象, 形式参数2对应的.class对象....):该方法不能获取私有构造方法
3、如果获取到的是私有的构造方法的构造器对象,需要调用构造器对象的setAccessible(true)方法
4、通过构造器对象的 newInstance(实际参数1, 实际参数2)创建对象,如果没有实际参数写null

举例
       1、通过 private Person(String name, int age)创建对象
            Class clazz =   Class.forName("com.itcast.Person");  //必须通过类全名获取
            Constructor con = clazz.get  Declared Constructor(String.class, int.class); //形式参数列表对应的.class列表
                   con.setAccessible(true); //此处不设置,无法创建该对象,因为构造方法是私有的
                   Object obj = con.newInstance("zhangsan",120);  //调用newInstance(实际参数列表)创建对象

      2、通过public Person()创建对象
              Class clazz =   Class.forName("com.itcast.Person"); //必须通过类全名获取
            Constructor con = clazz.getDeclaredConstructor(null);  //因为没有形式参数,所以写null
              con.setAccessible(true); //此处不设置,无法创建该对象,因为构造方法是私有的
                   Object obj = con.newInstance();  //因为不需要实际参数,所以调用无参的 newInstance方法

4.获取属性并调用

概述:
      java.lang.reflect.Field:属性管理器对象,可以对该类的对象的属性值进行修改和获取

步骤
      1、获取Class对象
      2、通过调用getDeclaredField("属性名")或通过调用getField("属性名")  获取属性管理器
      3、如果获取的是私有的属性,调用属性管理器的  setAccessible(true) 方法
      4、调用属性管理器的set(该类的对象,值) 来设置属性值
           调用属性管理器的get(该类的对象)来获取属性值

举例
            Person p1 = new Person();
                   Person p2= new Person(); 
                   Class clazz =   Class.forName("Person");  //第一步获取Class对象  
                   Field field = clazz.getDeclaredField("name"); 
    //第二步通过调用getDeclaredField("属性名")或通过调用getField("属性名")  获取属性管理器  
                   field.setAccessible(true);  //第三步如果获取的是私有的属性,调用属性管理器的setAccessible(true)方法  
                   field.set(p1, "张三");  //第四步用属性管理器的set(该类的对象,值) 来设置属性值
                   field.set(p2, "李四");
                   
                   System.out.println(field.get(p1));  //第四步调用属性管理器的get(该类的对象)来获取属性值  
                   System.out.println(field.get(p2));

5.获取成员方法并调用

概述:
       java.lang.reflect.Method:方法管理器,可以执行该类的对象的方法

步骤
      1、获取Class对象
      2、通过调用getDeclaredMethod("方法名",形式参数1.class, 形式参数2.class..)或通过调用geMethod("方法名",形式参数1.class, 形式参数2.class..)  获取属性管理器,如果没有形式参数写null
      3、如果获取的是私有的方法,调用方法管理器的  setAccessible(true) 方法
      4、通过属性管理器的invoke(该类的对象,实际参数)来执行方法,如果没有实际参数写null

案例
              Person p1 = new Person("张三",13); 
                   Person p2= new Person("李四",14); 
                   Class clazz =   Class.forName("Person"); 
                   
                   /* 
                   * 调用setName方法 
                   */ 
                   Method setName = clazz.getDeclaredMethod("setName", String.class); 
                   setName.setAccessible(true);  //如果getName方法是私有的,此处必须写   
                   setName.invoke(p1, "张三改"); 
                   
                   /* 
                   * 调用getName方法 
                   */ 
                   Method getName = clazz.getDeclaredMethod("getName", null);  //获取Person类的getName方法对应的方法管
                   getName.setAccessible(true);  //如果getName方法是私有的,此处必须写
                   Object object = getName.invoke(p1, null);  //执行p1对象的getName方法,并且将返回值赋值给object
                   System.out.println(object); 

6.反射练习

1: 通过反射修改成员变量的值,包括私有
2:   通过反射运行配置文件
   在JAVA项目下新建配置文件config,内容为:   class=Person name=jack
JAVA代码:
              Properties p = new Properties(); 
                   p.load(new FileReader("config")); 
                   String className   = (String)p.get("class"); 
                   String name = (String)p.get("name"); 
                   
                   Class clazz = Class.forName(className); 
                   //创建对象 
                   Constructor constructor = clazz.getConstructor(null); 
                   Object instance = constructor.newInstance(); 
                   
                   //通过setName设置name属性 
                   Method setName = clazz.getDeclaredMethod("setName", String.class); 
                   setName.invoke(instance,name ); 
                   
                   //通过getName设置name属性 
                   Method method = clazz.getDeclaredMethod("getName",null); 
                   Object object = method.invoke(instance, null); 
                   System.out.println(object);

3:   通过反射给   ArrayList<Integer> 中添加 String   类型的数据
                ArrayList  list = new ArrayList (); 
                   list.add(123); 
                   
                   
               Class clazz =   Class.forName("java.util.ArrayList");//必须通过类全名获取 
               Method method = clazz.getDeclaredMethod("add", Object.class); 
               method.setAccessible(true); 
               method.invoke(list, "ss"); 
               
               for(Object obj: list){ 
                       System.out.println(obj); 
               } 


 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值