zoukankan      html  css  js  c++  java
  • Java中的反射--Reflect

      在张孝祥老师的Java讲解中,学习到了Java反射的一部分知识,觉得有必要好好学习一下哈。

    一、反射的理解

    经典总结:反射就是把Java类中的各种成分映射成为相应的Java类

    例如:一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量、方法、构造方法、包等信息也用一个个的Java类来表示,表示Java类中的Class类显然要提供一系类的方法,来获得其中的变量、方法、构造方法、修饰类、包等信息,这些信息就是用相应的实例对象来表示,它们是Field、Method、Contructor、Package等

    反射的缺点:反射导致程序性能下降

    二、构造方法(Constructor)反射

    理解:就是获取到某一个Class类中的所有的构造方法Constructor类

    1 // 获得某个类的所有的构造方法
    2 Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
    3 
    4 // new String(new StringBuffer("abc"))
    5 // 得到String类的某一个构造方法
    6 Constructor constructor = String.class.getConstructor(StringBuffer.class);
    7 String str2 = (String) constructor.newInstance(new StringBuffer("abc"));

    三、成员变量(Field)反射

    理解:获取一个Class类中的成员变量的Field,以及通过反射获取其中某一个对象的成员变量的值

     1 public class ReflectPoint {
     2 
     3     private int x;
     4     public int y;
     5     
     6     public ReflectPoint(int x, int y) {
     7         super();
     8         this.x = x;
     9         this.y = y;
    10     }
    11 }
    12 
    13 ReflectPoint rf1 = new ReflectPoint(3, 5);
    14 // 获取Class类的Field成员变量,并没有指定是哪个对象的 fieldY不是对象上的变量,而是Class类上的变量,要用他去取某个对象上的值
    15 Field fieldY = rf1.getClass().getField("y");
    16 // 获取rf1这个对象的成员变量的值
    17 Object obj = fieldY.get(rf1);
    18 System.out.println(obj);
    19 
    20 // 获取Class类的Field成员变量,并没有指定是哪个对象的 这里x是私有的属性,但是也可以通过反射暴力获得
    21 Field fieldX = rf1.getClass().getDeclaredField("x");
    22 // 暴力反射
    23 fieldX.setAccessible(true);
    24 // 获取rf1这个对象的成员变量的值
    25 Object objX = fieldX.get(rf1);
    26 System.out.println(objX);

    注意:其中的注解也写的比较清楚,但是还想强调一下,Field类只是获取到了字节码中的成员变量,但是并没有获取到某一个特定对象的成员变量的具体的值

    成员变量反射的综合案例:

    题目:将任意一个对象中所有的String类型的成员变量所对应的字符串中的“b”转化成“a”,这其中用到了成员变量的反射,具体代码如下所示

     1 public class ReflectPoint {
     2 
     3     private int x;
     4     public int y;
     5     public String str1 = "ball";
     6     public String str2 = "basketball";
     7     public String str3 = "itcast";
     8     
     9     public ReflectPoint(int x, int y) {
    10         super();
    11         this.x = x;
    12         this.y = y;
    13     }
    14 }
    15 
    16     private static void changeStringValue(Object obj) throws Exception {
    17         Field[] fields = obj.getClass().getFields();
    18         for(Field field: fields){
    19             //if(field.getType().equals(String.class)){
    20             //这里就直接用 == 比较在内存中编译的字节码文件
    21             if(field.getType() == String.class){
    22                 String oldValue = (String) field.get(obj);
    23                 String newValue = oldValue.replace('b', 'a');
    24                 field.set(obj, newValue);
    25             }
    26         }
    27     }

    总结:其实这种反射的应用在spring框架的源码中应该是挺常见的,有时间去看看spring的源码,我想真正懂了反射的原理之后,再去读spring的源码的话,会轻松很多的!

    四、成员方法(Method)类

    理解:可以获取一个类中的成员方法

    1 String str1 = "abc";        
    2 
    3 Method methodCharAt = String.class.getMethod("charAt", int.class);
    4 // 注意这个invoke方法,这个是调用的意思,就是这个方法调用执行,传入new出来的对象以及参数
    5  System.out.println(methodCharAt.invoke(str1, 1));
    6 // 如果是静态方法的话,是不用传入new 出来的对象的,只需要传入参数即可
    7 // System.out.println(methodCharAt.invoke(null, 1));

    注意:静态方法,直接传入null即可,因为静态方法都是放在方法区中的,对象在栈中创建出来,就可以直接调用

    高能:用反射方式执行某个类中的main方法(写个程序,根据用户提供的类名,去执行该类中的main方法)

    为什么我很费劲的去用反射区调用main方法呢,这里其实可以引出一个前提条件,就是我并不知道到底是哪个类的main方法,但是类名可能就存在传递的参数中,我通过得到参数,得到类名,然后通过反射,启动main方法???

     1     static class TestArguments{
     2         public static void main(String[] args) {
     3             for(String arg:args){
     4                 System.out.println(arg);
     5             }
     6         }
     7     }
     8 
     9       //TestArguments.main(new String[]{"111","222","333"});
    10       String startingClassName = args[0];
    11       Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);
    12       mainMethod.invoke(null, (Object) new String[]{"111","222","333"});
    13    //mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});

    五、数组(Array)反射

    直接上代码吧,数组的反射应该在开发框架中会得到使用,直接看一下简单的代码吧,当然那个Array是java中的reflect包中的类:java.lang.reflect.Array

     1     private static void printObject(Object obj1) {
     2         Class clazz = obj1.getClass();
     3         
     4         if(clazz.isArray()){
     5             int len = Array.getLength(obj1);
     6             for(int i=0;i<len;i++){
     7                 System.out.println(Array.get(obj1, i));
     8             }
     9         }else{
    10             System.out.println(obj1);
    11         }
    12     }
    13 
    14         printObject(obj1);
    15         printObject(new int[]{1,2,3});
  • 相关阅读:
    7月的尾巴,你是XXX
    戏说Android view 工作流程《下》
    “燕子”
    Android开机动画bootanimation.zip
    戏说Android view 工作流程《上》
    ViewController里已连接的IBOutlet为什么会是nil
    My first App "Encrypt Wheel" is Ready to Download!
    iOS开发中角色Role所产生的悲剧(未完)
    UIScrollView实现不全屏分页的小技巧
    Apple misunderstood my app,now my app status changed to “In Review”
  • 原文地址:https://www.cnblogs.com/ssh-html/p/10633801.html
Copyright © 2011-2022 走看看