反射的基础是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);
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
1 //反射测试
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 }