了解反射,我是从类的定义入手的,首先,类是表示具有共同特性的事物的 集合,并将这个集合抽象成一个概念,这就是类。而java的一个类也具有它的 特征,比如类中有各种属性,方法,实现的接口等。所以也可以把java的类也 通过这些共性抽象成一个类。在java中把这个类取名叫Class。Class类就是表示 java各种类的一个类。 视频中描述的关于反射的概念,我觉得非常精辟!: 反射就是把java类中的各种成分映射成相应的java类。 比如把类中的属性映射成:Field类。 把构造方法映射成:Constructor类等等。
了解了这些,也很容易猜到这些Class类的作用,就是可以使用Class类的得到某 个类里面的各种属性、方法、接口等、并且可以用某个类生成它的实例对象,取 得对象里的属性、调用对象中的方法!
Class类: Class类的构造方法是私有化的,也就是说不能通过new来创建Class类的实例对象。 但它提供了Class.forName(String className)这个静态方法来生成一个实例对象。 也就是从文件的绝对路径名,可以生成Class类的实例对象。 也可以通过:类名.class 和 对象名.getClass()来得到Class类的实例对象。 关于*.Class其实就是*这个类的字节码文件···。
Field类: 表示java类中各种属性的一个类。 Method类: 表示java类中方法的类。 Constructor: 表示java类中构造方法的类。
通过以上的各种类,我们可以利用反射机制取得某个类的所有属性,实现的接口, 所有构造方法,以及成员方法。并可以利用这些产生实例对象,且得到此类的实例对 象中的各种属性和方法。
*由于数组也是引用类型,是Object的子类,我们同样可以利用反射机制操作数组。
以下是两个用于巩固学习的练习,ReflectPoint类是一个被测试的类,通过RelectTest 演示了如何使用反射调用ReflectPoint类的各种方法和操作此类对象的属性。 为了方便,直接Throws Exception```
定义一个ReflectPoint类:
package cn.hxq; public class ReflectPoint { private int x; public int y; public String str1 ; public String str2 ; public String str3 ; public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } public ReflectPoint(String str1, String str2, String str3) { super(); this.str1 = str1; this.str2 = str2; this.str3 = str3; } }
定义ReflectTest类:
package cn.hxq; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; public class ReflectTest { /** * @param args * */ public static void main(String[] args) throws Exception { //使用文件名得到ReflectPoint类 Class cls1 = Class.forName("cn.hxq." +"ReflectPoint"); //得到ReflectPoint类的两个构造方法,并用它们分别创建两个对象 Constructor con1 = cls1.getConstructor(int.class,int.class); ReflectPoint pt1 = (ReflectPoint)con1.newInstance(2,3); Constructor con2 = cls1.getConstructor(String.class,String.class,String.class); ReflectPoint pt2 = (ReflectPoint)con2.newInstance("ball", "basketball","icast"); //得到ReflectPoint类的两个int属性,并输出pt1对象里int属性的值。 Field fieldY = Class.forName("cn.hxq.ReflectPoint").getField("y"); System.out.println(fieldY.get(pt1)); Field fieldX = Class.forName("cn.hxq.ReflectPoint").getDeclaredField("x"); fieldX.setAccessible(true);//暴力反射,把私有属性抢过来。 System.out.println(fieldX.get(pt1)); //以下:将pt2对象里的String属性里所有的字符b换成字符a。 ChangeStringValue(pt2); System.out.println(pt2.str1+":"+pt2.str2+":"+pt2.str3); //以下:用反射调用String类对象的charAt方法。 Method methodCharAt = String.class.getMethod("charAt",int.class); System.out.println(methodCharAt.invoke(pt2.str1, new Object[]{0})); TestArguments.main(new String[]{"aaa","bbb","vccc"}); //以下:使用用户输入的参数来确定类名,并调用main方法。 String startingClassname = args[0]; Method mainMethod = Class.forName(startingClassname).getMethod("main", String[].class); mainMethod.invoke(null,(Object)new String[]{"aaa","bbb","vccc" }); int[] a1 = new int[]{1,2,3}; int[] a2 = new int[4]; int[][] a3 = new int[2][3]; String[] a4 = new String[]{"abc","ged","kfb"}; System.out.println(a1.getClass() == a2.getClass()); System.out.println(a4.getClass().getName()); System.out.println(a3.getClass().getSuperclass().getName()); //以下:看看数组与Object的关系。 Object obj1 = a1; Object obj4 = a4; Object[] obj3 = a3; System.out.println(Arrays.asList(a1)); System.out.println(Arrays.asList(a4)); System.out.println(Arrays.asList(a3)); System.out.println(Arrays.asList(obj3)); } public static void ChangeStringValue(Object obj)throws Exception{ 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); } } } }