黑马程序员-反射的应用

------- android培训java培训、期待与您交流! ----------


一、Constructor类

Constructor[] cons = String.class.getConstructors();			//得到String类的所有的构造方法
		
Constructor con = String.class.getConstructor(StringBuffer.class);	//得到StringBuffer类的一个的构造方法
String str = (String)con.newInstance(new StringBuffer("abc"));		//实例化Constructor对象

这里需要说明一下,

1、想要得到哪个构造方法的Constructor类就在getConstructor()方法里写上想得到的构造方法所传的参数类型的字节码;

2、在将Constructor进行实例化的时候的newInstance()方法中写的是这个构造函数所传参数的对象

3、最后需要将实例化对象强制转换成String类型,因为实例化之后返回类型是Object

String.class.newInstance();

最后也可以直接用过String类的字节码直接通过newInstance()方法,得到String的无参构造方法,然后通过无参的构造方法创建String的实例化对象,这个最后得到的也是Object,所以也要进行强制转换的哦


二、Field类

先写一个ReflectField类,记录两个变量,一个私有的x和一个共有的y,并建立有参的构造方法

private int x;
public int y;

public ReflectField(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}


ReflectField rf1 = new ReflectField(6,8);
//Field[] fields = rf1.getClass().getFields();//得到所有的变量放入到Field数组
Field fieldY = rf1.getClass().getField("y");
System.out.println(fieldY.get(rf1));
		
Field fieldX = rf1.getClass().getDeclaredField("x");
fieldX.setAccessible(true);		//暴力反射
System.out.println(fieldX.get(rp1));

需要注意的

1、得到ReflectField类的字节码后getField()方法这里需要写的是变量名

2、只是把y变量赋值给了fieldY,如果想得到y的值那么还要确定是哪个对象的里的y,所以fieldY的get()方法这里写的就是 ReflectField对象

3、由于x是私有的,所以如果想访问到变量x,就要用getDeclaredField()方法,将x变量赋值给fieldX;如果想打印x变量,则需要设置一个属性setAccessible(true)后就可以正常打印了


下边做一个练习,将一个对象里所有的String类型的变量所对应的字符串,将b改成Z

public static void ChangeValue(Object obj) {
	Field[] fds = obj.getClass().getFields();
	for(Field fd: fds)
	{
		try {
			if (fd.getType() == String.class) {
				String oldstr = (String) fd.get(obj);
				String newstr = oldstr.replace('b', 'Z');
				fd.set(obj, newstr);

			}
		} catch (Exception e) {
			
			throw new RuntimeException(e); 
		}
	}

}

注意:

1、field.getType()获取field这个变量的类型

2、如果类中的成员变量没有权限修饰,那么getFields()就需要变成getDeclaredFields();


三、Medthod类

String str1 = "abc";
Method methodCharAt = String.class.getMethod("charAt", int.class);//把String的charAt()方法赋给methodCharAt变量
System.out.println(methodCharAt.invoke(str1, 1));//调用methodCharAt的invoke()方法,打印结果为b
System.out.println(methodCharAt.invoke(str1, new Object[]{1}));//jdk1.4之前的书写方式,打印结果也是b

注意:

1、这里getMethod(),这里第一个是这个方法的名字;后边是这个方法传的参数

2、invoke()这里的str1是对象,后边的1是要给charAt这个方法传的参数(即,调用str1对象的chartAt(1)方法)

3、如果invoke()方法的第一个参数是null,那么这个charAt()方法不需要通过对象就可以调用,由此可以得出这个方法是静态方法。


四、数组的应用

Class cls = Class.forName("java.lang.String"); 
Object arr = Array.newInstance(cls, 10); //实例化一个长度为10的String类型数组
Array.set(arr, 5, "this is a test"); //将数组的第五个位置替换成"this is a test"
String s = (String) Array.get(arr, 5); //得到数组的第五个位置,并强制转换成String类型
System.out.println(s); 

Class cla = obj.getClass();
	if(cla.isArray()){		//判断cla是不是数组类型
		for(int i=0;i<Array.getLength(obj);i++){
			System.out.println(Array.get(obj, i));
		}
	}else{
		System.out.println(obj);
	}
判断如果是数组类型就挨个打印数组里的元素,如果不是数组类型就直接打印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值