zoukankan      html  css  js  c++  java
  • 反射

    反射

    将类的各个组成部分封装成其他对象

    好处

    1.可以在程序运行过程中,操作这些对象
    2.可以解耦,提高程序可扩展性
    
    如图,类文件通过类加载器载入时,类本身(注意不是类创造的对象)被分为三种对象,可分别对其操作

    获取Class对象的方式

    	1.Class.forName("全类名"): 将字节码文件加载进内存,返回Class对象
    		多用于配置文件,从文件中读取类名,加载类
    	2.类名.class: 通过类名的属性class获取
    		多用于参数的传递
    		Class cls2 = Calculate.class;
    	3.对象.class.getclass()方法
    		多用于对象获取字节码的方式
    		Calculate calculate1 = new Calculate();
    		Class cls3 = calculate1.getClass();
    	注:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。(注意区分class对象和堆内对象,class对象相当于方法区内的此类所在地址)
            System.out.println(cls1==cls2);
            System.out.println(cls1==cls3);
    //结果都是true
    

    Class对象获取功能

    1.获取成员变量们

    			* getFields(): 获取所有public修饰的成员变量
    				Field[] fields = cls1.getFields();
    			* getField(String name) 获取指定名称的public修饰的成员变量(private会报错)
    				Field field=cls1.getField("str");
    ------------------------------------------------------------------------------------------------------
    			* getDeclaredFields()  获取所有的成员变量,不考虑修饰符
    			* getDeclaredField(String name) 
    			//示例
            	Class cls1 = Class.forName("Calculate");   //加载Cal类
            	Field field=cls1.getDeclaredField("x");   //x为private修饰的变量
            	field.setAccessible(true);  //暴力反射,使field可修改x变量
            	Calculate calculate=new Calculate();//创建cal对象
            	field.set(calculate,12);//修改cal对象的值
    

    2.获取构造方法们

    			*  getConstructors()  
    			*  getConstructor()  
    			*  getDeclaredConstructor()  
    			*  getDeclaredConstructors()  
    
    		public Calculate(String str) {this.str = str;}
    		
    		Class cls1 = Class.forName("com.company.Calculate");
            Constructor cls = cls1.getConstructor(String.class);
            Calculate cal = (Calculate) cls.newInstance("liuyu");
            System.out.println(cal.str);
    

    3.3. 获取成员方法们:

    		* getMethods()  
    		* getMethod(String MethodName,Class... args) 
    		* getDeclaredMethods()  
    		* getDeclaredMethod(String MethodName,Class... args)  
    
    		public void add(Integer x,Integer y);
    		Class cls1 = Class.forName("com.company.Calculate");
            Method add = cls1.getMethod("add", Integer.class, Integer.class);
            Calculate calculate = new Calculate("sfd");
            System.out.println(add.invoke(calculate, 1, 2));
    

    4. 获取全类名

    		* String getName()  
    
    		Class cls1 = Class.forName("com.company.Calculate");
    		System.out.println(cls1.getName());
    //输出结果
    		com.company.Calculate
    

    反射实例(反射怎么方便我们)

    		* 需求:写一个"框架",不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法
    		* 实现:
    			1. 配置文件
    			2. 反射
    		* 步骤:
    			1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
    			2. 在程序中加载读取配置文件
    			3. 使用反射技术来加载类文件进内存
    			4. 创建对象
    			5. 执行方法
    
    //config.properties
            ClassName=com.company.Calculate
            MethodName=add
    //Main.java
                public static void main(String[] args) throws Exception {
    			String className, methodName;
    --------------------------------获取config.properties内容----------------------------------------
    			Properties in = new Properties();
    			ClassLoader classLoader = Main.class.getClassLoader();
            	InputStream inputStream = classLoader.getResourceAsStream("config.properties");
    			in.load(inputStream);
    			className = in.getProperty("ClassName");
    			methodName = in.getProperty("MethodName");
    -----------------------------------------------------------------------------------------------------------
    			Class cls = Class.forName(className);  //加载类
            	Constructor con = cls.getConstructor(String.class);  //获取构造函数
    			Object obj = con.newInstance("liuyu");//创建对象
    			Method method = cls.getMethod(methodName, Integer.class, Integer.class);//获取方法
                System.out.println(method.invoke(obj, 1, 2));//调用方法
        }
    
  • 相关阅读:
    git(常用命令)思维导图...
    有关gitlab的神秘操作.....version&&domain设置...
    Gitlab不小心关闭了sign-in,无法登录web的坑。。。
    聊聊CMSIS-RTOS是什么东东
    c#接口interface学习
    没有内置小鹤双拼的rime输入法就是差劲
    stm32中的型号对比——为什么很少用STM32F2,F3?
    stm32软件编程的框架及注意事项——rtos篇
    modbus-poll和modbus-slave工具的学习使用——modbus协议功能码3的解析(及欧姆龙温控器调试笔记)
    keil中error: #70: incomplete type is not allowed—解决方法
  • 原文地址:https://www.cnblogs.com/INnoVationv2/p/12356431.html
Copyright © 2011-2022 走看看