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});

猜你喜欢

转载自www.cnblogs.com/ssh-html/p/10633801.html