Java(反射Filed和Constructor类)


 

反射

反射就是把Java类中的各种成分映射成相应的java类。例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个类。表示java类的Class类显然要提供一系列的方法来获得其中的变量,方法,构造方法,修饰符,包等信息。这些信息就是用相应类的实例对象来表示,他们是Field、Method、Constructor、Package等

eg:
System.exit

System.getProperties()

就相当于Method-->methodObj1

-->methodObj2

-------------------------------------------------------------------------

Constructor类代表某个类中的一个构造方法

得到某个类所有的构造方法:

Constructor [] constructors = Class.forName("java.lang.String").getConstructor(StringBuffer.class);

//获得方法时要用到类型

创建实例对象:

通常方法:

// new String(new StringBuffer("abc"));用StringBuffer对象传给String这个构造方法,然后再new出一个实例对象

反射方法:

                 Constructor constructor1 = String.class.getConstructor(StringBuffer.class);//反射的方式实现,得到Constructor类型的对象;靠参数类型识别哪一个构造方法,(运行的时候才执行这行代码,在翻译的时候只是语法检查)
//		constructor1.newInstance(initargs);//字节码的对象,编译时到底对应String哪一个构造方法,不知道,
		constructor1.newInstance(new StringBuffer("abc"));
		//第一个StringBuffer是选择哪个构造方法;第二个是表示用这个构造方法的时候,传一个StringBuffer的对象进去
//		String str2 = constructor1.newInstance(new StringBuffer("abc"));//编译时不知道是谁的构造方法
		String str2 = (String)constructor1.newInstance(/*"abc"//这是String类型*/new StringBuffer("abc"));
		System.out.println(str2.charAt(2));

Class也提供newInstance,是为了提供便利

class-->constructor-->new object

Class.newInstance()寻找不带参数的构造方法,用构造方法创建实例对象。

反射导致程序性能严重下降。

--------------------------------------------------------------------

Filed类(字段,成员变量)

建一个类

public class ReflectPoint {

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

ReflectPoint pt1 = new ReflectPoint(3,5);
		Field fieldY = pt1.getClass().getField("y");	//pt1.class类的字节码.getField("y")用变量名字来区别成员变量
		//fieldY的值是多少;不是5,这个y代表的是字节码上的变量,并没有对应到对象身上,fieldY不代表具体的值,只代表某个变量,不代表这个变量上面	某个对象的值、(fieldY不是对象身上的变量,而是类上,要用它去取某个对象上对应的值)
		System.out.println(fieldY.get(pt1));
		Field fieldX = pt1.getClass().getDeclaredField("x");//声明过的就能看见	
		fieldX.setAccessible(true);//暴力反射
		System.out.println(fieldX.get(pt1));

---------------------------------------------------------

做一个扫描,对所有的a替换成b

思路简要分析:

我们要先把所有字段得到,也就是成员变量;然后遍历循环取值,然后替换,最后再set到fields里面

完整代码如下:

package com.itheima;

public class ReflectPoint {

	private int x;
	public int y;
	public String str1 = "ball";
	public String str2 = "basketball";
	public String str3 = "itcast";
	
	
	public ReflectPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}


	@Override
	public String toString() {
		return "ReflectPoint [x=" + x + ", y=" + y + ", str1=" + str1
				+ ", str2=" + str2 + ", str3=" + str3 + "]";
	}
	
	
}

package com.itheima;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class ReflectTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		String str1 = "abc";
		Class cls1 = str1.getClass();
		Class cls2 = String.class;
		Class cls3 = Class.forName("java.lang.String");
		System.out.println(cls1==cls2);
		System.out.println(cls1==cls3);
	
		System.out.println(cls1.isPrimitive());
		System.out.println(int.class.isPrimitive());
		System.out.println(int.class==Integer.class);
		System.out.println(int.class==Integer.TYPE);//定义一个常量TYPE,代表包装类型所包装的基本类型的字节码
		System.out.println(int[].class.isPrimitive());//数组也是类型,但是不是原始类型
		System.out.println(int[].class.isArray());
	
//		new String(new StringBuffer("abc"));用StringBuffer对象传给String这个构造方法,然后再new出一个实例对象
		Constructor constructor1 = String.class.getConstructor(StringBuffer.class);//反射的方式实现,得到Constructor类型的对象;靠参数类型识别哪一个构造方法,(运行的时候才执行这行代码,在翻译的时候只是语法检查)
//		constructor1.newInstance(initargs);//字节码的对象,编译时到底对应String哪一个构造方法,不知道,
		constructor1.newInstance(new StringBuffer("abc"));
		//第一个StringBuffer是选择哪个构造方法;第二个是表示用这个构造方法的时候,传一个StringBuffer的对象进去
//		String str2 = constructor1.newInstance(new StringBuffer("abc"));//编译时不知道是谁的构造方法
		String str2 = (String)constructor1.newInstance(/*"abc"//这是String类型*/new StringBuffer("abc"));
		System.out.println(str2.charAt(2));
		//Class.newInstance();
		ReflectPoint pt1 = new ReflectPoint(3,5);
		Field fieldY = pt1.getClass().getField("y");	//pt1.class类的字节码.getField("y")用变量名字来区别成员变量
		//fieldY的值是多少;不是5,这个y代表的是字节码上的变量,并没有对应到对象身上,fieldY不代表具体的值,只代表某个变量,不代表这个变量上面	某个对象的值、(fieldY不是对象身上的变量,而是类上,要用它去取某个对象上对应的值)
		System.out.println(fieldY.get(pt1));
		Field fieldX = pt1.getClass().getDeclaredField("x");//声明过的就能看见	
		fieldX.setAccessible(true);//暴力反射
		System.out.println(fieldX.get(pt1));
		
		changeStringValue(pt1);
		System.out.println(pt1);
		
	}

	private static void changeStringValue(Object obj)throws Exception {
		Field[] fields = obj.getClass().getFields();//得到所有字段
		for(Field field:fields){//给一个对象给我,然手扫面到所有成员变量,之后把值b改成a
			if(field.getType()==String.class){//同一份字节码要用==
			//field.getType()/*field是一个字段,是有类型的,所以.getType()*/.equals(String.class)
			String oldValue = (String)field.get(obj);//在对象身上取值,(String)我们知道他是String类型
			String newValue = oldValue.replace('b', 'a');//替换
			field.set(obj, newValue);
			
			}
		}
		
	}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值