----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
什么是反射?
反射就是把java类中的各种成分映射成相应的java类。
反射的基石——>Class
一个Java类用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机、变速箱等等也是一个个的类。表示Java类的Class类显然要提供一系列的方法,来获取其中的变量、方法、构造方法、修饰符、包等信息。这些信息就是用相应类的实例对象来表示,它们是File、Method、Contrutor、Package等等。
学习反射的要点
一个类中的每个成员都可以用相应的API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象
Constructor类 构造方法反射的应用
Constructor类代表某个类的构造方法
得到某个类的所有构造方法
Constructor counstructors[] = Class.forName("java.lang.String").getConstructors();
得到某一个构造方法
Constructor counstructor = Class.forName("java.lang.String").getConstructors(StringBuffer.class);
创建实例对象
通常方式:String str = new String(new StringBuffer("abc"));
反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));
调用获得的方法时,要用到上面相同类型的实例对象
String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
Class------->constructor-------------->new Object
由Class得到构造方法,由构造方法创建实例对象。
Field类 成员变量的反射
Field类代表某个类中的一个成员变量
暴力反射、以及将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的b改成a 实例如下:
public class ReflectPoint {
private int x = 0;
public int y = 0;
public String str1 = "abc";
public String str2 = "basketball";
public String str3 = "bai";
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
public String toString(){
return str1+":"+str2+":"+str3;
}
public int hashCoed(){
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class ReflectTest {
public static void main(String[] args) throws Exception{
ReflectPoint p1 = new ReflectPoint(3,7);
Field fieldY = p1.getClass().getField("y");
System.out.println(fieldY.get(p1));
//暴力反射
Field fieldX = p1.getClass().getDeclaredField("x");
fieldX.setAccessible(true);
System.out.println(fieldX.get(p1));
changeStringValue(p1);
System.out.println(p1);
}
private static void changeStringValue(Object obj) throws IllegalAccessException {
Field[] fields = obj.getClass().getFields();
for (int i = 0; i < fields.length; i++) {
if(fields[i].getType()== String.class){
String oldValue = (String)fields[i].get(obj);
String newValue = oldValue.replace('b', 'a');
fields[i].set(obj, newValue);
}
}
}
Method类 成员方法的反射
得到类中的某一个方法:
Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke(str,1);
注意:如果传递给Method对象的invoke()方法的一个参数为null,这有什么样的意义?
说明Method对象对应的是一个静态方法。
JDK1.4和JDK1.5的invoke方法的区别
jdk1.5:public Object invoke(Object obj,Object... args)
jdk1.4:public Object invoke(Object obj,Object[] args)
按jdk1.4的语法需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别应对被调用方法中的一个参数,所以,调用CharAt方法的代码也可以用jdk1.4改写为charAt.invoke("str",new Object[]{1})形式。
用反射方式执行某个类的main方法
写一个程序,这个程序能够根据用户名提供的类名,去执行该类中的main方法。
普通方式调用:Arguments.main(new String[]{"23","233"});
反射方式调用:Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);
mainMethod.invoke(null, (Object)new String[]{"aa","bb","cc"});
mainMethod.invoke(null, new Object[]{new String[]{"aa","bb","cc"}});编译器会做特殊处理,编译时不把参数当作数组看待,也就是不会把数组打散成若干个参数了。
数组的反射
什么样的数组是同一个Class
具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
代表数组的Class实例对象的getSuperClass方法返回的父类为Object类对应的class.
Arrays.asList()方法处理int[]和String[]时的差异
只能处理String[] 不能处理int[]
Araay工具类用于完成对数组的反射操作,它没有办法得到数组的类型,但可以得到元素的类型。
----------------------- android培训、java培训、java学习型技术博客、期待与您交流! ----------------------
详情请查看: