黑马程序员——Java高新技术之反射学习总结一

                    --------Java培训、Android培训、JavaEE培训、.NET培训、iOS培训期待与您交流!---------

                                                                                       反射学习总结

基础补充:

   Java程序中的各个Java类属于同一类事务,描述这类事务的Java类名就是Class

    Class对象代表内存中的一份字节码,所以不能直接通过new 关键字来实例化。

 

    字节码:.class文件编译好后是以二进制形式存放在内存中的。就是首相要将类的字节码加载到内存中去,之后用这个字节码去复制复制出一个个对象来。有几个类就会有几份字节码,就会有几份实例对象。

 

   得到字节码对应的实例对象的方式(Class类型):

     ①类名.class            

         Class clazz = Date.class; //代表Date类型的字节码

     ②对象.getClass()             

         Person p1 = new Person();

         p1.getClass(); //虽然有了对象,但是也可以调用对象的.getClass获取字节码

    ③Class.forName(类名)    

         Class.forName(“类的完整路径”);    //得到类的字节码

 可以发现得到类的字节码中有两种情况:

   情况一:这个类的字节码已经加载到内存中去了,这时只需找到字节码并返回

   情况二:获取这个类的字节码时发现虚拟机中还没有该类的字节码,这时用类加载器进   行加载,这时就用加载进来的字节码,调用该类的相应方法进行返回字节码。

查看是否该类是否为基本数据类型时,调用Class.isPrimitive方法,如果是返回true,如果不是返回false

只要在源程序中出现的类型,都有各自的Class实例对象,比如int[],void,等等


反射篇开始

   反射就是把Java类中的各种成分映射成相应的java类。

 

  1.Constructor类:代表某个类中的一个构造方法。

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

        Constructor[] constructors = Class.forName("java.lang.String").getConstructors();

     得到某一个构造方法:

        Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);

 创建实例对象:

        String str = (String)construtctor.newInstance(new StringBuffer("abc"));

//new String(new StringBuffer("abc"));
		Constructor constructor1 = String.class.getConstructor(StringBuffer.class);  //这里的StringBuffer代

		//表String的构造方法选择的是StringBuffer类型
		String  str = (String)constructor1.newInstance(new StringBuffer("abc"));  //表示用这个StringBuffer时

	//	要传一个StringBuffer进去,在创建时编译器不知道是String类型的,只有在运行时才会执行

		//String.class.getConstructor(StringBuffer.class);但在编译时没有读取constructor1后面的内容。

Class.newInstance()方法:

     该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。该方法内不的具体代码用到了缓存机制来保存默认构造方法的实例对象。

     比如:String obj = (String)Class.forName(“java.lang.String”).newInstance();


2.Field代表某个类中的一个成员变量。

     ReflectPoint类:

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

Reflect测试类:

import java.lang.reflect.Field;

public class ReflectTest {
	public static void main(String[] args) throws NoSuchFieldException,   SecurityException, IllegalArgumentException, IllegalAccessException {
		
		ReflectPoint rp = new ReflectPoint(2,5);
		Field fieldY = rp.getClass().getField("y");
		//fieldY不是对象身上的变量,而是类上,要用它去取某个对象上对应的值
		
		System.out.println(fieldY.get(rp));
		
		
	}
}

这时如果获取x变量时,会报java.lang.NoSuchFieldException:x异常。 

   可以将原来的.getField(“x”) 方法变为.getDeclaredField(“x”);即不论方法可见不可见都可以通过这个方法获取到,但是这是不可以取出来。这时可以用暴力反射

Field fieldX = rp.getClass().getDeclaredField("x");
		fieldX.setAccessible(true);  //这叫暴力反射
		System.out.println(fieldX.get(rp));


含有String类型的变量,进行反射

ReflectPoint类中:


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

在ReflectTest类中:

Field[] fields = rp.getClass().getFields();
		for(Field field : fields){
			//if(field.getType().equals(String.class)){
			//字节码用等号比
			if(field.getType() == String.class){
				String oldValue = (String)field.get(rp);
				String newValue = oldValue.replace('b', 'a');
				field.set(rp, newValue);
			}
}


3.Method代表某个类中的一个成员方法。

   

得到类中的某一个方法:

      Method charAt = Class.forName("java.lang.String").getMthod("charAt",int.class);

  普通方法:

     System.out.println(str.charAt(1));

   调用反射方法:

      System.out.println(charAt.invoke(str,1)); 

    

提示:如果传递给Method对象的invoke()方法的一个参数为null,说明该Method对象对应的是一个静态方法!也可以理解为,静态方法调用时不需要对象。



4.用反射方式执行某个类中的main方法

String startingClassName = args[0];
Method mainMethod =Class.forName(startingClassName).getMethod("main",String[].class);
//mainMethod.invoke(null,new Objectp[]{new String[]{"111","222","333"}});
mainMethod.invoke(null,(Object)new String[]{"111","222","333"});


5. 数组的反射

  具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。

   代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class

  int[][] a1 = new int[2][4];  //因为int[]属于Object类型的

  Object[] abj = a1;






CCF大数据与计算智能大赛-面向电信行业存量用户的智能套餐个性化匹配模型联通赛-复赛第二名-【多分类,embedding】.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值