反射的基础是Class类
Class:
JAVA类用于描述一类事物的共性。而是什么属性则是由类的实例对象来确定的,不同的实例对象有不同的属性值。
Class则是用于描述JAVA类的共性的类,描述了类的名字,访问属性,包名,字段名称列表,方法名称列表等。
Class的实例对象为某个类的字节码。
获取字节码的实例对象方法有三种
1. 类名.class System.class
2. 对象.getClass new Date().getClass()
3. Class.forName("类名") Class.forName("java.util.Date")
Class cls1=Date.class //Date类的字节码 ,已经加载到内存
Class cls2=p1.getClass();//调用对象的getClass()得到类的字节码
Class.forName("java.lang.String") //返回该类字节码
反射就是把Java类中的各种成分映射成相应的Java类,如:一个Java类中用Class类的对象来表示,一个类中组成的部分:
成员变量,方法,构造方法,包等信息,也是用一个个Java类来表示的
Class代表一份类字节码
Method 类的实例对象代表 类的方法
Constructor类
Constructor类代表类中的一个构造方法
//获取某个类的所有构造方法
Constructor[] constructors=Class.forName("java.lang.String").getConstructors();
//获取某个构造方法,要用的参数类型 如:String(StringBuffer buffer)
Constructor constructor=Class.forName("java.lang.String").getConstructor(StringBuffer.class);
创建实例对象
通常方法:String str=new String(new StringBuffer("abcd"));
//Constructor类的 newInstance() 方法
反射方法:String str=(String)constructor.newInstance(new StringBuffer("abc"))
Field类,代表某个类的属性
Field fieldy=pt1.getClass().getField("y"); 得出的是类的属性,值是不固定的,根据对象来确定
fieldy.get(pt1);
改field需要调用fieldy.set(obj,value);
Method类
getMethod(name,parameterytpes) //类名,方法参数类型
//执行方法用invoke(obj,parameters)
Method methodCharAt=String.class.getMethod("charAt",int.class)
//静态方法 name=null
methodCharAt.invoke(str1,1);
2 public class ReflectPoint {
3 private int x;
4 public int y;
5 public String str1 = " china " ;
6 public String str2 = " basketbool " ;
7 public String str3 = " itcast " ;
8 public ReflectPoint( int x, int y) {
9 super ();
10 this .x = x;
11 this .y = y;
12 }
13
14 }
15
2 import java.lang.reflect. * ;
3 public class ReflectTest {
4
5 /** 反射基本知识
6 *
7 * 反射就是把java类中的各个成分映射为java类
8 * 反射的基础是Class类,它是java类的描述类,Class类的实例是某个类的字节码
9 * @param args
10 */
11 public static void main(String[] args) throws Exception {
12 // TODO Auto-generated method stub
13 // Class测试
14 // Class的实例是类的字节码
15 String str1 = " abcde " ;
16
17 // 获取Class实例的三种方式
18 Class cls1 = str1.getClass(); // 获取该对象类的字节码
19 Class cls2 = String. class ; // 直接调用类的字节码
20 Class cls3 = Class.forName( " java.lang.String " ); // 根据类名获取字节码
21
22 System.out.println(cls1 == cls2); // true
23 System.out.println(cls1 == cls3); // true
24
25 // isPrimitive()是否是基本数据类型的字节码 8种+void
26 System.out.println(cls1.isPrimitive()); // false
27 System.out.println(Integer. class .isPrimitive()); // false
28 System.out.println( int . class .isPrimitive()); // true
29
30 // Integer.TYPE常量 代表包装的基本类型 的 字节码
31 System.out.println( int . class == Integer.TYPE); // true
32
33 // 数组不是基本数据类型,是对象
34 System.out.println( int []. class .isPrimitive()); // false
35 System.out.println( int []. class .isArray()); // true
36
37 // 得到String类的 String(StringBuffer)构造方法
38 Constructor constructor = String. class .getConstructor(StringBuffer. class );
39 // 可以构造方法,创建实例 ,并进行类型转换
40 String str2 = (String)constructor.newInstance( new StringBuffer( " abcsd " ));
41
42 ReflectPoint pt1 = new ReflectPoint( 3 , 5 );
43
44 // Field类
45 Field fieldy = pt1.getClass().getField( " y " );
46 // fieldy的值是5吗? 不是,fieldy不代表具体的值,只代表类的y变量
47 // 因为取的是类的字节码,类中变量的值是根据 对象来决定的
48 // 通过.get(object) 来获取某个对象的值
49 System.out.println(fieldy.get(pt1));
50
51 Field fieldx = pt1.getClass().getDeclaredField( " x " ); // 获取声明过的属性
52 fieldx.setAccessible( true ); // 访问权限设置为true
53 System.out.println(fieldx.get(pt1));
54
55 changeString(pt1);
56 System.out.println(pt1.str1);
57 System.out.println(pt1.str2);
58 System.out.println(pt1.str3);
59
60 // Method
61 // 取得类字节码 中的charAt方法
62 Method methodCharAt = String. class .getMethod( " charAt " , int . class );
63 // 调用invoke(obj,parameter) 执行方法
64 System.out.println(methodCharAt.invoke(str1, 1 ));
65
66
67 // 调用main()方法,普通方式
68 // TestArguments.main(new String[]{"abc","1111"});
69 // 使用反射调用,为了解决,给定类名,而不知道实现代码的情况下用
70 // 从类字节码 得到 main方法
71 Method methodmain = Class.forName(args[ 0 ]).getMethod( " main " ,String[]. class );
72 methodmain.invoke( null , new Object[]{ new String[]{ " abc " , " 1111 " }});
73
74 // 数组的反射
75 int [] a1 = new int [ 3 ];
76 int [] a2 = new int [ 4 ];
77 int [][] a3 = new int [ 2 ][ 3 ];
78 String[] a4 = new String[ 2 ];
79 // 数组的字节码比较,看的是数组类型和数组维度
80 System.out.println(a1.getClass() == a2.getClass()); // true
81 System.out.println(a1.getClass() == a3.getClass()); // false
82 System.out.println(a1.getClass() == a4.getClass()); // false
83 System.out.println(a3.getClass() == a4.getClass()); // false
84 // 获取父类
85 System.out.println(a1.getClass().getName());
86 System.out.println(a1.getClass().getSuperclass().getName());
87 System.out.println(a4.getClass().getSuperclass().getName());
88 // 得出父类都是Object类
89 Object aobj1 = a1;
90 Object aobj2 = a2;
91 Object aobj4 = a4;
92 // Object[] aobj5=a1; // 里面装的是基本类型,基本类型不是对象,不能装入
93 Object[] aobj5 = a3;
94
95 int [] t1 = new int []{ 12 , 34 , 2 };
96 printObject(t1); // 打印对象,数组是对象,但t1数组元素是基本类型
97 printObject( " xyz " ); // 打印对象
98
99 }
100
101 private static void printObject(Object obj){
102 Class clazz = obj.getClass(); // 获取该对象类的字节码
103 if (clazz.isArray()){
104 // Array是数组的反射类
105 for ( int i = 0 ;i < Array.getLength(obj);i ++ ){
106 System.out.println(Array.get(obj, i));
107 }
108 } else {
109 System.out.println(obj);
110 }
111 }
112
113 private static void changeString(Object obj){
114 Field[] fields = obj.getClass().getFields();
115 for (Field field:fields){
116 if (field.getType() == String. class ){ // 同一份字节码 用==
117 try {
118 String newValue = ((String)field.get(obj)).replace( ' a ' , ' b ' );
119 field.set(obj, newValue);
120 } catch (Exception e) {
121 // TODO: handle exception
122 }
123 }
124 }
125 }
126 }