一、Class类
- 众多的人属于同一类事物,我们可以用Person类来表示。Java中的各个Java类也属于同一类事物,描述这类事物的Java类名就是Class。
- Person类的实例对象是一个个具体的人,如张三;Class类的实例对象则是各个类在内存中的字节码。(一个类被类加载器加载到内存中,占用一片存储空间,这片空间中的内容就是类的字节码)
- 获得各个字节码对应的实例对象 1.类名.class 2.对象.getClass() 3.Class.forName("类名")
二、反射
反射就是把Java类中的各种成分映射成相应的java类。成员变量、方法、构造方法等信息用Field类、Method、Constructor表示等。
三、构造方法的反射——Constructor类
import java.lang.reflect.Constructor;
public class ConstructorDemo {
/**
* Constructor类代表某个类中的一个构造方法
* 1.得到某个类所有的构造方法
* Constructor constructors[] = Class.forName("java.lang.String").getConstructors();
* 2.得到某一个构造方法
* Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
* 3.创建实例对象
* 通常方式:String str = new String(new StringBuffer("abc"));
* 反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));
*/
public static void main(String[] args)throws Exception {
//new String(new StringBuffer("abc"));
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
String newString = (String)constructor1.newInstance(new StringBuffer("abc"));
System.out.println(newString);
}
}
四、成员变量的反射——Field类
首先创建一个ReflectPoint类,含有一个私有成员x和公有成员y。
public class ReflectPoint {
private int x;
public int y;
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
import java.lang.reflect.Field;
public class FieldDemo {
/**
* Field类代表某个类中的一个成员变量
*/
public static void main(String[] args)throws Exception {
ReflectPoint rp1 = new ReflectPoint(1, 2);
ReflectPoint rp2 = new ReflectPoint(3, 4);
//因为x是私有的
Field fieldX = rp1.getClass().getDeclaredField("x");
fieldX.setAccessible(true);
System.out.println("rp1.x=" + fieldX.get(rp1));
System.out.println("rp2.x=" + fieldX.get(rp2));
//y是公有的
Field fieldY = rp1.getClass().getField("y");
//fieldY的值是多少?是2?错!fieldY不是某一个对象身上的变量,而是该类上的,要用它去取某个对象上对应的值
System.out.println("rp1.y=" + fieldY.get(rp1));
System.out.println("rp2.y=" + fieldY.get(rp2));
}
}
例题:将任意一个对象中的所有String类型的成员变量所对应的字符串中的"b"改为"a"。
public class ReflectPoint {
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "itcast";
@Override
public String toString() {
return "ReflectPoint [str1=" + str1 + ", str2=" + str2 + ", str3=" + str3 + "]";
}
}
import java.lang.reflect.Field;
public class ClassDemo {
public static void main(String[] args) throws Exception {
ReflectPoint pt1 = new ReflectPoint(1, 2);
changeStringValue(pt1);
System.out.println(pt1.toString());
}
private static void changeStringValue(Object obj) throws Exception {
// 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('b', 'a');
field.set(obj, newValue);
}
}
}
}
五、成员方法的反射——Method类
import java.lang.reflect.Method;
public class MethodDemo {
/**
* Method类代表某个类中的一个成员方法
* 1.得到类中的某一个成员方法
* Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
* 2.调用方法
* 通用方式:System.out.println(str.charAt(1));
* 反射方式:System.out.println(charAt.invoke(str,1));
*/
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
Method methodcharAt = String.class.getMethod("charAt", int.class);
System.out.println(methodcharAt.invoke(new String("abc"), 1));
}
}
当参数是一个数组时,jdk1.4会把这一个数组参数当作数组长度个参数。例如,
main(new String[]{"aaa","bbb","ccc"}),实际上是一个字符串数组作为参数,但编译器会当作是三个字符串参数。
应该写成main(new object[]{new String[]{"aaa","bbb","ccc"}})
六、数组的反射
- 具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
- 基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当作Object类型使用,又可以当作Object[]类型使用。