zoukankan      html  css  js  c++  java
  • 反射:框架设计的灵魂

    *框架:半成品软件。可以在框架的基础上进行软件开发,简化编码

    其实,用框架并不一定用得到反射。但是,如果你要开发一套框架供别人使用,就得用到反射。但是,如果我们知道了反射机制,就能在使用框架时游刃有余。

    *反射:将类的各个组成部分封装为其他对象,这就是反射机制。

    例如:将成员变量封装为Field对象;构造函数-->Constructor对象;成员方法-->Method对象

    *获取class对象的方式:

    1.Class.forName("全类名");将字节码文件加载进内存,返回Class对象(对应源代码阶段)*多用于配置文件,将类名定义在配置文件中,返回class对象

    2.类名.class:通过类名的属性class获取(对应class类对象阶段)*多用于参数的传递

    3.对象.getClass():getClass()方法在Object类中定义着 *多用于对象的获取字节码的方式

    结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的class对象都是同一个。

     好处:1.可以在程序的运行过程中去操作这些对象。例如,String str 这个对象创建之后,str.  后会提示很多方法。这些方法其实就是str对象加载到内存之后,程序运行中程序提供的操作这些对象的方式。

     /*Class对象功能:
        *获取功能:
        1.获取成员变量们:
        *Field[] getFields();---获取所有public 修饰的成员变量
        *Field getField(String name)----获取指定名称的public修饰的成员变量
        *Field[] getDeclaredFields()----获取所有成员边浪
        *Field getDeclaredField(String name)
        *
        *操作:
        *1.设置值    2.获取值
        *2.获取构造方法们
        *Constructor<> getConstructors()
        *Constructor<> getConstructor(类<>..parameterTypes)
        *Constructor<> getDeclaredConstructor(类<>..parameterTypes)
        *Constructor<>[] getDeclaredConstructor()
        *
        *3.获取成员方法们:
        *Method[] getMethods()
        *Method getMethod(String name,类<>...parameterTypes)
        *Method[] getDeclaredMethods()
        *Method getDeclaredMethod(String name,类<>..parameterTypes)
        *
        *4.获取类名
        *String getName()
        */

    2.可以解耦。来达到程序的可扩展性。

    package cn.itcast.junit;
    
    import java.text.DateFormat.Field;
    
    public class ReflectDemo {
        
        public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
            //获取Person的class对象
            Class personClass=Person.class;
            /*1.获取成员变量们:
            *Field[] getFields();
            *Field getField(String name)
            *Field[] getDeclaredFields()
            *Field getDeclaredField(String name)
            **/
            //1.Field[] getFields();---获取所有public 修饰的成员变量
            java.lang.reflect.Field[] Feilds=personClass.getFields();
            for(java.lang.reflect.Field filed:Feilds){
                System.out.println(filed);
                //public java.lang.String cn.itcast.junit.Person.a
            }
            
            //*Field getField(String name)----获取指定名称的public修饰的成员变量
            Person p=new Person();
    、 //Field 是对象 。对象就有方法。通过对象的方法完成操作。具体操作参见API文档 java.lang.reflect.Field f
    =personClass.getField("a");
    、    //此时 f 为获取的 person 类中的String a 参数。如下对 f 进行设置值与赋值 f.set(p,
    "这是通过设置成员方法设置的值");//操作成员变量---设置成员变量的值 Object value=f.get(p); System.out.println(value); //*Field[] getDeclaredFields() System.out.println(" ================="); java.lang.reflect.Field[] filed = personClass.getDeclaredFields(); for(java.lang.reflect.Field f1:filed){ System.out.println(f1); } //*Field getDeclaredField(String name) //这里不能访问 d java.lang.reflect.Field f3=personClass.getDeclaredField("d"); Person p2=new Person(); //会报错 //f3.set(p2, "这是通过获取成员变量而设置的值"); //System.out.println(f3.get(p2)); //访问前忽略权限修饰符的安全检查---"暴力反射" f3.setAccessible(true); f3.set(p2, "这是暴力反射后获取成员变量而设置的值"); System.out.println(f3.get(p2)); } }

    案例:

    *需求:写一个“框架”,可以帮我们创建任意类的对象,并且执行其中任意的方法(在不改变该类的任何代码的前提下)。

    *实现:

    1.配置文件  2.反射

    *步骤

    1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中

    2.在程序中加载读取配置

    3.使用反射技术来加载类文件进内存

    4.创建对象

    5.执行方法

    文件列表+配置文件:(实现在不改变任何源代码的前提下,通过改变配置文件来达到获取不同类下的不同方法,并执行)

    package cn.itcast.reflection;
    
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.Properties;
    
    import org.omg.CORBA.portable.InputStream;
    
    /*
     * 框架类
     * */
    public class ReflectTest {
    	//可以创建任意类的对象,可以执行任意方法
    	public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
    		/*前提:不能改变该类的任何代码,可以创建任意类的对象,可以执行任意方法*/
    		
    		//1.加载配置文件
    		//1.1 创建Properties对象
    		Properties pro =new Properties();
    		//1.2加载配置文件,转换为一个集合
    		//1.2.1 获取文件class目录下的配置文件
    		ClassLoader classLoader=ReflectTest.class.getClassLoader();
    		java.io.InputStream is=classLoader.getResourceAsStream("pro.properties");
    		System.out.println(is);
    		pro.load(is);
    		//2.获取配置文件中配置的数据
    		String className=pro.getProperty("className");
    		//System.out.println(className);
    		String methodName=pro.getProperty("methodName");
    		//System.out.println(methodName);
    		//3.加载该类进内存
    		Class cls=Class.forName(className);
    		//创建对象
    		Object obj=cls.newInstance();
    		//System.out.println(obj);
    		//获取方法对象
    		Method method=cls.getMethod(methodName);
    		//执行方法
    		method.invoke(obj);
    		
    	}
    }
    
  • 相关阅读:
    进程空间与系统空间(一)
    内核之最
    Linux 内核3.10.5 专场
    device_create与device_register
    重写与重载的含义
    抽象类和接口的区别
    Spring知识点
    mybatis学习
    知识点
    Mybatis面试题
  • 原文地址:https://www.cnblogs.com/laoyangtou/p/12299131.html
Copyright © 2011-2022 走看看