JAVA高新技术——反射机制Reflection


反射的作用

可以于运行时加载、探知、使用编译期间完全未知的classes。Java程序可以加载一个运行时才得知名称的class,

获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。


Class类

a.class、b.class是两个类,他们同样有共性的东西,如都有名字,构造方法等等。把他们抽象成一个特殊的类Class类。
故a.class、b.class他们都是Class的类的实例对象,当他们被类加载器加载到内存时,占用一部分空间,这部分空间就叫做 字节码
不同的类字节码是不同的,即在内存空间的内容是不同的,这一个个空间可分别用一个个对象来表示-----a.class、b.class
获取各个字节码对应的实例对象有三种方法:
1,类名.class
2,对象.getClass()
3,Class.forName("类名")
第三种方法在反射常用。因为写代码时不知道类名,需要当做变量。

注:无论哪种方法,字节码实例对象如果相同则在内存中只有一份。如String.class在内存中只有一份。

Constructor类

Constructor类代表某一类的构造方法。
通过字节码实例对象.getConstructor(参数类型的字节码)获取类的指定参数的构造方法。
在通过Constructor类中的newInstenc(参数)方法创建对象。

例子:
		/*用反射完成:String st=new String(new StringBuffer("abc"));*/
		
		//先获得带参数的构造方法
		Constructor constructor=
				Class.forName("java.lang.String").getConstructor(StringBuffer.class);
		//再利用构造器中的newInstence方法创建对象
		String st=(String)constructor.newInstance(new StringBuffer("abc"));
		System.out.println(st);

Field类

Field类代表某个类的成员变量。
例子:
假定已有ReflectPoint类,其成员为private int x,public int  y;
获取public成员变量的值:
通过字节码实例对象.getField("成员变量名")获取Field类对象,通过Field类对象的get(对象)方法得到某一对象的成员变量的值。
		/*利用反射Field得到类的字段(成员变量),先定义好一个Point类模拟*/

		ReflectPoint pt=new ReflectPoint(1,6);
		Field fieldY=pt.getClass().getField("y");
		//fiedldY不是具体的值,不是6,他是字节码文件的成员变量,得到某个对象的值需要用get方法
		System.out.println(fieldY.get(pt));
获取private成员变量的值:
注意方法区别
		//暴力反射,得到私有成员变量及其值
		Field fieldX=pt.getClass().getDeclaredField("x");
		//上面只是让你得到私有成员,但取不出来,还需要一步
		fieldX.setAccessible(true);
		System.out.println(fieldX.get(pt));

练习:利用反射,将任意对象中的所有String类型的成员变量对应的字符串内容中的字母b改成a

public class ReflectStr {
	public String str1="babababa";
	public String str2="aaaaaab";
	public String str3="bbbaaaccc";
	@Override
	public String toString() {
		return "ReflectStr [str1=" + str1 + ", str2=" + str2 + ", str3=" + str3
				+ "]";
	}	
}

import java.lang.reflect.Field;

/*
 * 利用反射,将任意对象中的所有String类型的成员变量对应的字符串内容中的字母b改成a
 * 思路:
 * 	先定义一个测试类ReflectStr,并定义对象
 * 	得到对象的字节码文件,利用反射Field得到字节码的所有成员变量
 * 遍历成员变量如果类型为String则得到其值
 * 利用String方法将其值中的b改成a得到新的String
 * 再将成员变量的值设置成新的字符串
 * */
public class ReflectTest1{
	public static void main(String[] args) throws Exception {
		ReflectStr st=new ReflectStr();
		System.out.println(st); //之前的字符串
		
		func(st);
		System.out.println(st);//之后的字符串
	}
	//封装方法
	private static void func(Object obj) throws Exception{
		// TODO Auto-generated method stub
		Field[] fields=obj.getClass().getFields();
		for(Field field:fields){
			//由于字节码文件只有一个,所以用==而不必用equals
			if(field.getType()==String.class){
				String oldValue=(String)field.get(obj);
				String newValue=oldValue.replace('b', 'a');
				field.set(obj, newValue);
			}
		}
	}
}

Method类

Method类代表某个类中的一个成员方法。
通过字节码实例对象.getMethod(“方法名”,方法参数类型的字节码)获取Method对象。
再利用invoke方法实现功能。
例子:
		String str1=new String("abc");
		/*利用反射完成str1.charAt(2)*/
		
		//获得字节码,并得到字节码中的指定方法charAt对象
		Method method=str1.getClass().getMethod("charAt", int.class);
		//charAt方法对象调用方法类中的invoke方法实现charAt功能
		System.out.println(method.invoke(str1, 2));

练习:利用反射调用别的类的主函数
//别的主函数
 class TestClass{
	public static void main(String[] args){
		for(String arg:args){
			System.out.println(arg);
		}
	}
}
执行下面代码时,记得将上面的类名当做参数传递给下面类的主函数参数。
import java.lang.reflect.Method;

public class ReflectMethod {
	public static void main(String[] args)throws Exception {
	
		/*利用反射调用别的类的主函数*/
		//一般方法:TestClass.main(new String[]{"111","222","333"});
		//需要知道为什么要用反射?写代码时,不知道调用哪个类的主函数,类的名字需要当参数传递
		String startingClassName=args[0];
		Method mainMethod= Class.forName(startingClassName).getMethod("main", String[].class);
		/*
		 *	mainMethod.invoke(null, new String[]{"111","222","333"});
		 *这句话有两点注意:
		 *第一个参数一般是需要调用方法的对象,当null时,说明方法是静态的
		 *第二个参数由于JDK1.5需要兼容JDK1.4,故当参数为数组时,会把数组的参数拆开
		 *故这句话的参数会当做有4个。又两种解决方法
		*/

		mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});
		//或mainMethod.invoke(null, (Object)new String[]{"111","222","333"});
	}
}






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【1】项目代码完整且功能都验证ok,确保稳定可靠运行后才上传。欢迎下载使用!在使用过程中,如有问题或建议,请及时私信沟通,帮助解答。 【2】项目主要针对各个计算机相关专业,包括计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师或企业员工使用。 【3】项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 【4】如果基础还行,或热爱钻研,可基于此项目进行二次开发,DIY其他不同功能,欢迎交流学习。 【注意】 项目下载解压后,项目名字和项目路径不要用中文,否则可能会出现解析不了的错误,建议解压重命名为英文名字后再运行!有问题私信沟通,祝顺利! 基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip基于C语言实现智能决策的人机跳棋对战系统源码+报告+详细说明.zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值