java反射的学习,好多东西不太理解,
主要分析了constructor,method,field,数组和调用main函数等反射的多个方面小例子。
主要的练习类
1 package javaAdvanced;
2
3 import java.lang.reflect.*;
4 import java.util.Arrays;
5
6 /**
7 * 类的描述信息
8 * 反射的练习
9 *
10 * @author cuiH
11 * @since 1.5
12 */
13 public class ReflectTest {
14
15 /**
16 * 反射:将java中各个成分 映射到相应的java类上面
17 * 就是说你想去到java类的一些信息,就需要用到反射。(类信息层面的控制)
18 */
19
20 public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException, ClassNotFoundException {
21
22 //constructor类(构造方法的反射)
23 Constructor constructor = String.class.getConstructor(StringBuffer.class);
24 String strTest = (String) constructor.newInstance(new StringBuffer("cuiHuan")); //调用该方法时候也需要声明类型
25
26 System.out.println(strTest.charAt(3)); //运行时刻该constructor对应的是StringBuffer, constructor在编译运行时刻进行转换,泛型进行约束
27 /**
28 * 作用,得到每个类的构造方法
29 * 然后调用该方法下面的构造器
30 * 正常情况下是:class——》constructor->new object
31 * 使用constructor->调用 constructor,调用obj
32 */
33
34
35 //field类的使用(字段),反射调用字段
36 ReflectPoint pt1 = new ReflectPoint(3, 5);
37 Field fieldY = pt1.getClass().getField("y"); //得到字节码,得到field,field是类上的某个域,去取相应对象上的该域
38 fieldY.get(pt1); //去到数值
39 System.out.println(fieldY.get(pt1));
40
41 /**
42 * result:java.lang.NoSuchFieldException 若是getFiled访问私有方法时:报错没有改域
43 * 对于私有需要用 getDeclaredField
44 */
45 Field fieldX = pt1.getClass().getDeclaredField("x");
46 fieldX.setAccessible(true);
47 System.out.println(fieldX.get(pt1));
48 /**
49 * result:java.lang.IllegalAccessException 提示非法错误,可以进行去到,但是仍然无法用,
50 * 需要暴力输出:fieldX.setAccessible(true); 强制设定为可以进入(暴力进入)
51 */
52
53 //利用反射,进行对源程序进行修改。例如修改已经打完jar包的程序。
54 changeStringValueBToA(pt1);
55 Field[] fieldStr = pt1.getClass().getFields();
56 System.out.println("b变为a更改后为:");
57 for (Field field : fieldStr) {
58 System.out.println(field.get(pt1));
59 }
60
61
62 //Method 类 反射调用方法 (方法调用方法,invoke调用该方法)
63 Method methodCharAt = String.class.getMethod("charAt", int.class);
64 methodCharAt.invoke(strTest, 3);
65 System.out.println(methodCharAt.invoke(strTest, 3));
66 /**
67 * 获取方法(踩刹车)
68 * 调用方法(刹车调用停车的方法),面向对象的设计
69 * 相当于获取了静态方法,静态引入
70 * 注意jdk1.4之前没有可变参数,
71 */
72 System.out.println(methodCharAt.invoke(strTest, new Object[]{3}));//jdk 1.4的做法,声明一个数组来代替可变参数(原始方法)
73
74
75 TestArguments.main(new String[]{"cuiHuan", "like", "java"}); //调用main方法,原有的静态的调用方法
76 String className = "javaAdvanced.TestArguments";
77 Method mainMethod = Class.forName(className).getMethod("main", String[].class);
78 mainMethod.invoke(null, new Object[]{new String[]{"cuiHuan", "like", "java"}});
79
80 //数组的反射
81 int[] a1 = new int[]{2, 1, 3};
82 int[] a2 = new int[4];
83 int[][] a3 = new int[2][3];
84 String[] a5 = new String[2];
85 String[] a6 = new String[3];
86 String[] a4 = new String[]{"a", "b", "c"};
87 System.out.println("数组比较:" + (a1 == a2)); //没有赋值之前为 true ;赋值之后为false
88 System.out.println("String比较:" + (a5 == a6)); //没有赋值之前为 true ;赋值之后为false
89 System.out.println("a1字节码的名字:" + a1.getClass().getName());
90 System.out.println("a2字节码的名字:" + a2.getClass().getName());
91 System.out.println("数组字节码比较:" + (a1.getClass() == a2.getClass())); //说明用的是一个字节码
92 System.out.println("一维数组的父类的字节吗的名字:" + a1.getClass().getSuperclass().getName()); //数组的父类是obj
93 System.out.println("二维数组的父类的字节吗的名字:" + a3.getClass().getSuperclass().getName()); //数组的父类是obj
94 System.out.println("String的父类的字节吗的名字:" + a4.getClass().getSuperclass().getName()); //数组的父类是obj
95
96 Object obj1 = a1; //数组其实是一个对象
97 Object obj2 = a4;
98 Object[] obj3 = a4; //二维数组其实是一组对象
99 Object[] obj4 = a3;
100 System.out.println("直接输出a1:" + a1); //result: 直接输出a1:[I@16c9ba38 类型为I(int) 具体数值为@16c9ba38
101 System.out.println("输出为string的a1:" + Arrays.toString(a1)); //result:输出为string的a1:[2, 1, 3]
102 System.out.println("输出为list的a1:" + Arrays.asList(a1)); //result: 输出为list的a1:[[I@15e0be38] 证书看做了一个参数(相当于一个obj)
103 System.out.println("直接输出数组:" + a4); //result:直接输出数组: [Ljava.lang.String;@95c7850
104 System.out.println("输出为list的a1:" + Arrays.asList(a4)); //字符串可以成功转换为Llist
105
106 /**
107 * 之前可以发现,数组的本质一个对象,二维相当于一组对象,对于asList获取的是对象的地址
108 * 当数组或者String没有初始化之前,他们共用一个字节码。(object)
109 *
110 * 数组反射的应用
111 * 现在如果要改变数组的其中一个元素
112 */
113 System.out.println("数组反射的应用:打印数组中的每个元素");
114 printObject(new int[]{2, 1, 3}); //result:2 1 3
115 printObject(new int[4]); //result: 0 0 0 0 默认数值都是0
116 printObject("String"); //result:String
117
118
119 }
120
121 //打印数组的函数
122 private static void printObject(Object obj) {
123 Class cls = obj.getClass();
124 if (cls.isArray()) {
125 int length = Array.getLength(obj);
126 for (int i = 0; i < length; i++) {
127 System.out.print(Array.get(obj, i) + " ");
128 }
129 } else {
130 System.out.println(obj);
131 }
132
133 }
134
135 //有许多String类型,将所有String中的b 变为 a
136 private static void changeStringValueBToA(Object obj) throws IllegalAccessException {
137 Field[] fields = obj.getClass().getFields();
138 for (Field field : fields) {
139 //判定是String的字节码
140 if (field.getType() == (String.class)) { //字节码最好不用Equals比 较,双等号比较好,因为字节码只有一个,唯一
141 String oldValue = (String) field.get(obj);
142 String newValue = oldValue.replace('b', 'a');
143 field.set(obj, newValue);
144 }
145 }
146 }
147
148
149 }
150
151 //写一个方法,调用main方法
152 class TestArguments {
153 public static void main(String[] args) {
154 for (String arg : args) {
155 System.out.println(arg);
156 }
157 }
158 }
用到的一个java类:
1 package javaAdvanced;
2
3 /**
4 * 类的描述信息
5 * 反射信息的测试类
6 *
7 * @author cuiH
8 * Date: 13-12-2
9 */
10 public class ReflectPoint {
11 private int x;
12 public int y;
13
14 public String str1 = "football";
15 public String str2 = "basketball";
16 public String str3 = "pingPang";
17
18 public ReflectPoint(int x, int y) {
19 this.x = x;
20 this.y = y;
21 }
22
23 @Override
24 public String toString() {
25 return super.toString();
26 }
27
28 @Override
29 public boolean equals(Object o) {
30 if (this == o) return true;
31 if (!(o instanceof ReflectPoint)) return false;
32
33 ReflectPoint that = (ReflectPoint) o;
34
35 if (x != that.x) return false;
36 if (y != that.y) return false;
37
38 return true;
39 }
40
41 @Override
42 public int hashCode() {
43 int result = x;
44 result = 31 * result + y;
45 return result;
46 }
47 }