------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
1、反射就是把java类中的各种成分映射成相应的java类
要认识反射,首先要知道Class类,这个和class关键字不同,它是一个类,描述java类字节码文件的类。
2、获取该类对象的方法有三个:类名.class
new Date().getClass();
Class.forName("完整的类名-包名加类名");
<span style="font-size:14px;"> String str = "abc";
Class<String> cls1 = (Class<String>) str.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");</span>
这三个Class对象表示的都是同一个字节码文件,可以使用==来判断一下他们是否指向同一个对象:
<span style="font-size:14px;"> System.out.println(cls1==cls2);
System.out.println(cls1==cls3);</span>
打印输出的结果都是:true,true,表示这三个方法获取的Class对象都是指向同一个。
在java中有九个预定义的 Class 对象,他们是八个基本数据类型和void对应的.class字节码文件,即int.class,char.class等。
他们还可以使用他们的包装类引用包装类中的静态成员变量TYPE,例如:Boolean.TYPE, Character.TYPE。
3、Class类中的方法boolean isPrimitive()可以判定指定的Class对象是不是基本类型,只有是上面的9种Class对象才返回真。
4、Class类中的Constructor<?> getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它表示此 Class
对象所表示的类的指定公共构造方法。
例如:
<span style="font-size:14px;"> Constructor cons = String.class.getConstructor(StringBuffer.class);</span>
这个就是获取String类中参数是StringBuffer类型的构造方法。
如果要获取全部的构造方法可以使用Constructor<?>[] getConstructors(),它返回的是一个Constructor数组
5、使用Constructor类中的方法newInstance()可以创建相对应的类对象,但是在传参数时注意要和getConstructor()方法
中的参数类型相对应,例如:
<span style="font-size:14px;"> String str = (String)cons.newInstance(new StringBuffer("abc"));</span>
同时要注意的是要对创建的对象进行类型转换,因为java不能识别你创建的对象到底是什么类型的。
6、Field 类,Class类中的getField方法可以获取指定Class对象的Field对象,该对象反映此Class
对象表示的类的成员变量,但
是 这个方法只能获取被public修饰的成员变量,如果要获取私有的成员变量要使用getDeclaredField方法,这个方法只要是在 类中声明过的都能获取到。
类ReflectPoint:
<span style="font-size:14px;">public class ReflectPoint {
private int x;
public int y;</span>
<span style="font-size:14px;"> public String str1 = "abc";</span>
<span style="font-size:14px;"> public String str1 = "abc";
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
}</span>
获取Field对象的方法:
<span style="font-size:14px;">ReflectPoint rp1 = new ReflectPoint(3, 5);
//获取ReflectPoint类中的xy成员变量,由于X是私有的,只能使用getDeclaredField方法,只要是在类中声明的都可以获取
//其中fx,fy代表的不是对象rp1对象中xy的值,而是一个变量,要获取rp1对象中xy的值使用get(Object)方法,
//但是fx要先使用setAccessible将fx设置为true,才能获取rp1对象中x的值
Field fx = rp1.getClass().getDeclaredField("x");
Field fx = rp1.getClass().getField("x");
Field fy = rp1.getClass().getField("y");
fx.setAccessible(true);</span>
上面的Field fx = rp1.getClass().getField("x");这一行就会报
Exception in thread "main" java.lang.NoSuchFieldException: x异常
这个时候就可以使用Field中的方法获取类ReflectPoint中对象rp1 x,y想对应的值,要注意的是fx,fy并不表示对象rp1中x,y的值。但是在获取rp1对象的X的值要先调用Field父类AccessibleObject中的setAccessible方法,将fx对象的accessible值设置为true,这样就可以使用Object get(Object obj) 方法获取rp1对象中x,y的值,注意这个方法返回的是Object对象,
如果要将返回的值赋给一个int型变量的话,要做转型。例如:
<span style="font-size:14px;"> fx.setAccessible(true);
int i = (Integer)fx.get(rp1);
System.out.println(i);
System.out.println(fx.get(rp1));
System.out.println(fy.get(rp1));</span>
7、使用反射将类ReflectPoint中的String类型成员变量中的字符o全部替换成b
private static void changeChar(Object obj) throws Exception, IllegalAccessException {
// TODO Auto-generated method stub
Field[] fields = obj.getClass().getFields();
for (Field field : fields) {
if (field.getType()==String.class) {
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('o', 'b');
field.set(obj, newValue);
}
}
}
调用方法,打印rp1对象中str1和str2的只
changeChar(rp1);
System.out.println(rp1);
输出结果
abc:hellb wbrld