反射——框架设计的灵魂

反射:框架设计的灵魂

   *框架: 半成品软件,可以在框架的基础上进行软件开发,美化编码
   *反射: 将类的各个组成部分封装为其他对象,这就是反射机制
                好处:
                      1.  可以在程序运行过程中操作这些对象。
                      2.  可以解耦,提高程序的可扩展性。
    Java代码在计算机中经历的三个阶段      Source阶段     Class类对象阶段    Runtime阶段

    *获取Class对象的三种方式
    Source阶段         1.Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
                        *多用于配置文件,将类名定义在配置文件中。读取文件,加载类
    Class类对象阶段     2.类名.class: 通过类名的属性class获取
                        *多用于参数传递
    Runtime阶段        3.对象.getClass():getClass()方法在Object类中定义着
                        *多用于对象的获取字节码的方式
        结论:
                * 同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,
                    不论通过哪一种方式获取的Class对象都是同一个

Class对象的功能
*1.获取成员变量们
* Field[] getFields() 获取所有public 修饰的成员变量
* Field getField(String name) 获取指定名称的public 修饰的成员变量
* Field[] getDeclaredFields() 获取所有的成员变量 不考虑修饰符
* Field getDeclareField(String name) 获取指定的成员变量 不考虑修饰符

package reflect;

import java.lang.reflect.Field;

public class ReflectDemo1 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //1.获取Person的Class对象
        Class personClass=Person.class;

        /*
        *1.获取成员变量们
        *       Field[]  getFields()     获取所有public 修饰的成员变量
        *       Field    getField(String name)   获取指定名称的public 修饰的成员变量
        *       Field[]  getDeclaredFields()    获取所有的成员变量 不考虑修饰符
        *       Field    getDeclareField(String name)   获取指定的成员变量  不考虑修饰符
        * */

        //1.Field []   getFields()
        Field[]fields=personClass.getFields();
        for (Field field:fields){
            System.out.println(field);
        }
        System.out.println("----------------------");

        //获取指定名称的public 修饰的成员变量
        Field a=personClass.getField("a");
        //获取成员变量a的值
        Person p=new Person();
        Object value=a.get(p);
        System.out.println(value);
        //设置a的值
        a.set(p,"张三");
        System.out.println(p);

        //Field [] getDeclaredFields[]    获取所有的成员变量,不考虑修饰符
        Field[] declaredFields=personClass.getDeclaredFields();
        for (Field declaredfield : declaredFields) {
            System.out.println(declaredfield);
        }
        //Field getDeclaredField(String name)访问指定想成员变量,不考虑修饰符
        Field d=personClass.getDeclaredField("d");
        //忽略访问权限的修饰符的安全检查
        d.setAccessible(true);//暴力反射
        Object value2=d.get(p);
        System.out.println(value2);
    }
}

    *2.获取构造方法们
           *       Constructor<?>[]  getConStructors()  获取所有public 修饰的构造方法
           *       Constructor<T> getDeclaredConstructor(类<?>...parameterTtpes) 获取指定public 修饰的构造方法

           *       Constructor<T> getDeclaredConstructor(类<?>...parameterTypes)  获取所有构造方法,不考虑修饰符
           *       Constructor<?> [] getDeclaredConstructors()                  获取指定构造方法,不考虑修饰符
package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class ReflectDemo2 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        //1.获取Person的Class对象
        Class personClass = Person.class;

        /*2.获取构造方法们
        *       Constructor<?>[]  getConStructors()                     获取所有public 修饰的构造方法
        *       Constructor<T> getDeclaredConstructor(类<?>...parameterTypes) 获取指定public 修饰的构造方法

        *       Constructor<T> getDeclaredConstructor(类<?>...parameterTypes)  获取所有构造方法,不考虑修饰符
        *       Constructor<?> [] getDeclaredConstructors()                  获取指定构造方法,不考虑修饰符

         */

        //Constructor<T> getDeclaredConstructor(类<?>...parameterTypes)   可以传多个值
        //获取指定public修饰的构造器
        Constructor constructor=personClass.getConstructor(String.class,int.class);
        System.out.println(constructor);
        //创建带参对象
        Object person=constructor.newInstance("倪涛涛",23);
        System.out.println(person);

        Constructor constructor1=personClass.getConstructor();
        System.out.println(constructor1);
        //创建无参对象
        Object person2=constructor1.newInstance();
        System.out.println(person2);

        //空参创建无参对象的简化方法
        Object o=personClass.newInstance();
        System.out.println(o);
        //暴力反射
        //constructor.setAccessible(true);
    }

}

    *3获取成员方法们
           *       Method[] getMethod()             获取所有public 修饰的成员方法
           *       Method<T> getMethod(String name,类<?>...parameterTypes)   获取指定public修饰的成员方法

           *       Method[] getDeclaredMethods()     获取所有成员方法
           *       Method getDeclaredMethod(String name,类<?>...parameterTypes)  获取指定成员方法
package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectDemo3 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {

        /*
        *  *3获取成员方法们
         *       Method[] getMethod()             获取所有public 修饰的成员方法
         *       Method<T> getMethod(String name,类<?>...parameterTypes)   获取指定public修饰的成员方法

         *       Method[] getDeclaredMethods()     获取所有成员方法
         *       Method getDeclaredMethod(String name,类<?>...parameterTypes)  获取指定成员方法

         *
        * */
        //1.获取Person的Class对象
        Class personClass = Person.class;
        //获取指定名称的方法
        personClass.getClass();
        Method eat_method=personClass.getMethod("eat");
        Person p=new Person();
        //执行方法   invoke(Object obj)
        eat_method.invoke(p);

        Method eat_method2=personClass.getMethod("eat",String.class);
        //执行方法
        eat_method2.invoke(p,"饭");

        System.out.println("*****************");

        //获取所有public修饰的方法    !!! 这里也会有父类Object类的方法
        Method[]methods=personClass.getMethods();
        for(Method method:methods){
            System.out.println(method);
            //暴力反射
            method.setAccessible(true);
            //获取方法名
            String name=method.getName();
            System.out.println("方法名"+name);
        }

        //获取类名
            String className=personClass.getName();
            System.out.println("类名"+className);//全类名:  包名+类名
    }

}

    *4获取类名
           *        String getName()

``package reflect2;

import domen.Person;
import reflect.Student;

public class reflectDemo1 {
/*
*
* *获取Class对象的三种方式
Source阶段 1.Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
Class类对象阶段 2.类名.class: 通过类名的属性class获取
Runtime阶段 3.对象.getClass():getClass()方法在Object类中定义着

* */
public static void main(String[] args) throws Exception {
    //1. Class.forName("全类名")   即包名.类名
    Class cls1=Class.forName("domen.Person");
    System.out.println(cls1);
    //2. 类名.class
    Class cls2= Person.class;
    System.out.println(cls2);
    //3. 对象.getClass()
    Person p=new Person();
    Class cls3=p.getClass();
    System.out.println(cls3);

    //用==去比较三个对象
    System.out.println(cls1==cls2);//true
    System.out.println(cls2==cls3);//true
    System.out.println(cls1==cls3);//true

    Class cls4=Student.class;
    System.out.println(cls1==cls4);//false
}

}

package reflect;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class ReflectTest {
public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//可以创建任意类的对象,可以执行任意方法
/*
* 前提:不能改变该类的任何代码,可以创建任意类的对象,可以执行任意方法
* */
// Person p=new Person();
// p.eat();
//1.加载配置文件
//1.1 创建Propertires对象
Properties pro=new Properties();
//1.2 加载配置文件,转换为一个集合

    //1.2.1获取class目录下的配置文件  可以用 类加载器
    ClassLoader classLoader=ReflectTest.class.getClassLoader();
    //classLoader.getResource();//获取资源的路径
    //获取资源的字节流
    InputStream is=classLoader.getResourceAsStream("pro.properties");
    pro.load(is);
   // is.close();
    //2.获取配置文件中定义的数据
    String className=pro.getProperty("String");
    String methodName=pro.getProperty("methodName");

    //3.加载该类进内存
    Class cls=Class.forName(className);
    //4.创建对象
    Object obj=cls.newInstance();
    //5.获取方法对象
    Method method=cls.getMethod(methodName);
    //6.执行方法
    method.invoke(obj);
}

}


 * Field:成员变量
            *操作:
                    1.设置值
                            *void set(Object obj,Object value)
                    2.获取值
                            *get(Object obj)
                    3.忽略访问权限修饰符的安全检查
                            * setAccessible(true):暴力反射
 * Constructor:构造方法
            *创建对象:
                    * T newInstance(Object...initargs)

                    * 如果使用空参数操作对象,是可以简化的:
                                                Class对象的newInstance方法

 * Method: 方法对象
                *执行方法:
                            *   Object invole(Object objmObject...args)
                *获取方法名称
                            *   String getName():获取方法名

 * 案例:
            *需求:写一个“框架”,不改变该类的任何代码前提下,可以帮我们创建任意类的对象,并且执行其中任意方法
                *实现:
                        1.配置文件
                        2.反射
                *步骤:
                        1.将需要创建的对象的全类名和需要执行的方法定义在配置文件中
                        2.在程序中加载读取配置文件
                        3.使用反射技术加载类文件进内存
                        4.创建对象
                        5.执行方法


发布了48 篇原创文章 · 获赞 18 · 访问量 4344

猜你喜欢

转载自blog.csdn.net/niTaoTaoa/article/details/103021851