反射机制

反射机制

     反射的基本概念

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


Class

   表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是FieldMethodContructorPackage等等。

   一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象


    字节码 :

    一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示

   三种获得字节码的方式:

    类名.class();

       对象.getClass();

       Class.forName(“类名”);

	String str = "asd";
	//输出结果为class java.lang.String
	System.out.println(String.class);
	System.out.println(str.getClass());
	System.out.println(Class.forName("java.lang.String"));

    九个预定义Class实例对象:

         分别为:char,short,byte,int,long,float,double,booleanvoid.

         Class.isPrimitive可以检查是否为基本类型

     Int.class ==Integer.TYPE 

         Class.isArray()

	System.out.println(int.class);                  //int
	System.out.println(int.class.isPrimitive());    //true
	System.out.println(int.class == Integer.TYPE);  //true<span lang="EN-US">
</span>

      Constructor

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

根据构造方法的参数的个数和类型,来获取不同的构造方法.方法的各个参数的类型用Class对象表示


	//得到某个类中所有构造方法
	Constructor[] con = Class.forName("java.lang.String").getConstructors();
	//获得某个类并创建
	Constructor constructor = String.class.getConstructor(StringBuffer.class);
	String str1 = (String)constructor.newInstance(new StringBuffer("itheima"));
	System.out.println(str1);


    可以利用泛型提前确定数据类型省去强制类型转换

        Constructor<String> constructor2 = String.class.getConstructor(StringBuffer.class);
	String str2 = constructor2.newInstance(new StringBuffer("itheima"));

   

    Class类提供货了newInstance()方法用于直接构造没有参数的类

	String.class.newInstance();


 Field

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

public static void main(String[] args) throws Exception{
		Point p = new Point(1,4);
		
		//获得public属性的值
		Field fieldY = p.getClass().getField("y");
		//类中的非静态的属性需要一个对象来取出这个对象中的值
		System.out.println(fieldY.get(p)); 
		
		//获取private属性的值
		//私有属性不能使用getField()方法
		Field fieldX = p.getClass().getDeclaredField("x");
		//获得私有属性后,需强制破解才能获得或修改值
		fieldX.setAccessible(true);
		fieldX.set(p, 12);
		
		//获得类的静态属性
		Field fieldZ = p.getClass().getField("z");
		System.out.println(fieldZ.get(Point.class));
	}

}

class Point {
	
	private int x;
	public int y;
	public static int z = 0;
	
	public Point(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	
}

    作业:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"

package com.itheima.reflect;

import java.lang.reflect.Field;

public class replaceChar {
	public static void main(String[] args) {
		TestClass test = new TestClass();
		System.out.println("替换前" + test);
		replaceCharB(test);
		System.out.println("替换后" + test);
	}

	private static void replaceCharB(Object obj) {
		Field[] fields = obj.getClass().getFields();
		
		for(Field field : fields) {     
			if(field.getType() == String.class) {     //检测是否为String  
				String str = null;
				try {
					str = (String)field.get(obj);   
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
				
				String newStr = str.replace('b', 'a');    //replace方法不会改变str的原值

				try {
					field.set(obj, newStr);          //将str重新设置回去
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

class TestClass {
	public String str1 = "bbbbbbbbbbbbb";
	public String str2 = "babfbdsbd";
	public String str3 = "ball";
	public int i = 0;
	@Override
	public String toString() {
		return "TestClass [str1=" + str1 + ", str2=" + str2 + ", str3=" + str3
				+ ", i=" + i + "]";
	}
}


        Method
   

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

	String str = "abc";
	//调用String类的chatAt(int) 方法
	Method stringCharAt = String.class.getMethod("charAt", int.class);
	System.out.println(stringCharAt.invoke(str, 1));
    当Method.invoke(null, )方法的第一个参数为null时,代表Method方法为静态方法.


      main方法的反射:

mian方法传递String数组数据的两个解决办法:

mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});

mainMethod.invoke(null,(Object)new String[]{"xxx"});,编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了

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


      数组的反射

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

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

基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;

非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。

	public static void main(String[] args) {
		int[] a1 = new int[3];
		int[] a2 = new int[4];
		int[][] a3 = new int[1][3];
		String[] a4 = new String[1];
		a4[0] = "sdfs";
		System.out.println(a1.getClass() == a2.getClass());
		System.out.println(a1.getClass() == (Object)a3.getClass());
		System.out.println((Object)a1.getClass() == a4.getClass());
		//不加强制转换会直接报错  不知道为什么  强制转换加到哪是一样的
		
		System.out.println(a1.getClass().getName());
		System.out.println(a3.getClass().getSuperclass().getName());
		
		Object o1 = a1;
		Object o2= a4;
		//Object[] o3 = a1;
		Object[] o4 = a3;
		Object[] o5 = a4;
		
		//Arrays类
		
		System.out.println(Arrays.asList(a3));
		
		
		Object obj;
		printObject(a1);
	}

//利用数组的反射输出数据
	private static void printObject(Object obj) {
		Class claszz = obj.getClass();
		if(claszz.isArray()){
			int len = Array.getLength(obj);
			for(int i=0; i<len; i++){
				System.out.println(Array.get(obj, i));
			}
		}else{
			System.out.println(obj);
		}
	}

    简单框架实例

  

   框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。

public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
		//根据配置文件来调用配置文件中的Collection的子类
		String objectClass;
		
			FileInputStream fis = new FileInputStream("ReflectClass.Properties");
			Properties pro = new Properties();
			pro.load(fis);
			fis.close();
			objectClass = pro.getProperty("objectClass");
			Class cla = Class.forName(objectClass);
			Collection collection = (Collection)cla.newInstance();
		
	}


   配置文件的位置

       配置文件应尽量写绝对路径,最好在使用时专门设置一个放配置文件的目录

    类名.Class.getClassLoader.getResourceAsStream(String name)
     可以指定当前包下的文件


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值