记录反射技术的知识点(一)

2014-11-24 03:07:06 · 作者: · 浏览: 9

反射这个词在平常中我们并不常见,但是对于进阶java技术我们是不的不学习的.

java反射就是将类中的各个成分(构造函数,字段,方法)映射成一一对应的类.

反射的步骤:

1.获取到类的Class对象

2.通过Class对象获取构造函数对象(Constructor),字段对象(Field),方法对象(Method).

3.通过这些类某部分所映射出来的对象,结合某个具体的对象来获取对应对象该部分的值.

1)获取Class的方法用String类为例在(java.lang.String)包中

//获取class方法
		Class a1 = Class.forName(java.lang.String);
		Class a2 = String.class;
		Class a3 = new String().getClass();
		System.out.println(a1==a2);//true
		System.out.println(a1==a3);//true

注意:

得到的Class对象(字节码)在内存中没个类有且只有一份(类只会加载一次),所以上面会输出两个true.

2)通过反射获取构造方法以 String(StringBuffer sb);这个构造方法为例

                Constructor
  
    c = String.class.getConstructor(StringBuffer.class);
		String sb = c.newInstance(new StringBuffer(abc));
		System.out.println(sb.charAt(1));//b
  

注:

第一句,首先获取到String对应的Class对象 之后通过getConstructor的方法获取到String类参数列表为StringBuffer的构造函数。

第二句,调用这个构造函数对象中的newInstance来实例化一个Sring对象。

第三句,利用我们刚创建的string对象来获取abc串中中的b

补充:

如果是想通过无参数的构造方法来创建string对象那么有更简便的方法:String.class.newInstance();类直接创建。

为了方便我创建AAA这个类

class AAA{
	public int x;
	private int y;
	public String s1;
	public String s2;
	public String s3;
	public AAA(){}
	public AAA(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	public AAA(String s1,String s2,String s3){
		this.s1 = s1;
		this.s2 = s2;
		this.s3 = s3;
	}
	public static void main(String[] args) {
		for(String s:args){
			System.out.println(s);
		}
	}
	
}

3)通过反射获取AAA类的字段值

//反射方法获取变量
		AAA a11 = new AAA(1,2);
		Field fx = a11.getClass().getField(x);//获取AAA类所有对象的公共字段的值
		System.out.println(fx.get(a11));//1
		Field fy = a11.getClass().getDeclaredField(y);//获取私有的字段
		fy.setAccessible(true);//强制访问
		System.out.println(fy.get(a11));//2

注:第二是获取AAA这个类中所有对象的共有的x字段,第三行是制定获取AAA类中具体哪个对象中的x的值。

第四和第五行同样的获取,只不过是获取的私有字段

4)通过反射修改该类对象中字段中的值

//修改对象中的字段值
		AAA al2 = new AAA(ydcun123,hello123,abcde123);
		Field[] fs = al2.getClass().getFields();
		for(Field f: fs){
			//因为是比较获取的这个字段是什么类型,string字节码在内存中有且只有一份
			if(f.getType()==String.class){
				String oldString = (String) f.get(al2);
				String newString = oldString.replace('1', 'a');
				f.set(al2, newString);
			}
		}
		System.out.println(al2.s1+:+al2.s2+:+al2.s3);//ydcuna23:helloa23:abcdea23


5)通过反射获取到类中的方法以String类中的charAt方法为例:

String s2 = new String(abcde);
Method meth = s2.getClass().getMethod(charAt, int.class);//找charAt的方法参数是int型
System.out.println(meth.invoke(s2, 4));//e//第一个参数指定用那个对象执行,要是为null代表这个方法是静态的,第二个就是具体参数
		

6)调用AAA类中的main方法

                String classp = AAA;//AAA类的完整路径
		Class cp = Class.forName(classp);
		Method methP = cp.getMethod(main, String[].class);
		//为了兼容1.4版本中的new Object[]{} 来传递多个参数,他会吧我们要整体传入的参数给拆包
		//methP.invoke(null,new Object[]{new String[]{ydcun,abcdef,ggg}});
		methP.invoke(null, (Object)new String[]{ydcun,abcdef,ggggg});
				

7)数组反射

                int[] arr1 = new int[]{1,2,3};
		int[] arr2 = new int[4];
		int[][] arr3 = new int[2][3];
		String[] arr4 = new String[]{123,abc,mnh,ggg};
		System.out.println(arr1.getClass() == arr2.getClass());
		//下面两个直接不行
		//System.out.println(arr1.getClass() == arr3.getClass());
		//System.out.println(arr1.getClass() == arr3.getCla