反射(1)—基本知识

  • 一、反射,被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能操作任意对象内部属性及方法。
    • 正常方式:引入需要的“包类”名称–>通过new实例化–>取得实例化对象
    • 反射方式:实例化对象–>getClass()方法–>得到完整的“包类”名称
  • 二、功能:
    • 1.在运行时判断任意一个对象所属的类
    • 2.在运行时构造任意一个类的对象
    • 3.在运行时判断一个类所具有的成员变量和方法
    • 4.在运行时调用任意一个对象的成员变量和成员方法
    • 5.生成动态代理
  • 三、Class类:对照镜子可以得到的信息,包括某个类的方法、属性、构造器、实现的那些接口,对于每个类而言JRE为每个类都保存了一个不变的Class类对象,一个Class对象包含了特定某个类的有关信息
    • 1.Class本身也是一个类
    • 2.Class对象是能由系统建立对象
    • 3.一个类在JVM中只有一个Class实例
    • 4.一个Class对象对应的是一个加载到JVM中的一个.class文件
    • 5.每个类的实例都会记得自己是由哪个Class实例所生成的
    • 6.通过Class可以得到完整的一个类的完整结构
  • 四、步骤:

    • 1.创建Class对象 Calss cla = Person.class,编辑时只是编辑成.class文件,运行时才会加载到内存
    • 2.使用newInstance()创建运行时对象,比如:Person p = cla.newInstance();
    • 3.获取运行时类的属性,比如name属性,Field f1 = cla.getField(“name”)
    • 4.并设置属性,比如name,f1.set(p, “李斯”);
  • 五、代码:

public class TestReflection {

    //若不使用反射,如何创建一个对象,并调用其中的方法、属性 
    /*@Test
    public void test1(){
        Person p = new Person();
        p.setAge(22);
        p.setName("张三");
        System.out.println(p.toString());
        p.display("HK");

    }*/
    //使用反射创建对象
    @Test
    public void test2() throws Exception{
        Class<Person> cla = Person.class;

        //1.首先创建cla对应的运行时类Person类的对象
        Person p = cla.newInstance();
        System.out.println("反射机制创建对象:"+p);

        //2.通过反射调用并设置运行时类指定的属性
        //设置属性有两种方法,
        //其一这个属性的权限修饰符为public,使用getField()
        Field f1 = cla.getField("name");//首先获取一个属性,属性的名字叫name,赋给Field类型的变量f1
        f1.set(p, "李斯");                //其次为这个属性赋值,对象為Person,属性名为name,f1调用set方法为属性赋值
        System.out.println("为对象的一个属性name赋值:"+p);//输出这个对象
        //其二.这个属性的权限修饰符为private,使用getDeclareField()
        Field f2 = cla.getDeclaredField("age");
        //设置私有的变量允许访问。
        f2.setAccessible(true);
        f2.set(p, 22);
        System.out.println("为对象的第二个属性age赋值:"+p);
        //3.通过反射调用运行时方法,有二种其一方法有参数,方法无参数
        Method m1 = cla.getMethod("display",String.class);
        m1.invoke(p,"中国");//invoke(对象,方法形参) 
    }
    /**
     * java.long.Class类是反射的源头,getClass()返回值类型是Class类型。
     *创建一个类,通过编译(javac.exe)生成相应的.class文件,
     *之后使用java.exe加载(JVM类加载器完成).class文件,此.class文件加载到内存之后就是一个运行时类,存到缓冲区。
     *那么这个运行时类本身就是一个Class的实例。
     *1.每个运行时类只加载一次
     *2.有了Class类的实例之,才可以进行如下操作:
     *  ①创建对应的运行时类对象
     *  ②获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在包、异常、注解...)
     *  ③调用运行时类的指定结构(属性、方法、构造器)
     *  ④反射的应用:动态代理
     */
    @Test
    public void test3() throws Exception{
        Person p = new Person();
        Class clas= p.getClass();//获取该对象的类名,由哪个类创建的,以及包名路径
        System.out.println(clas == Person.class);
        System.out.println(clas);//clas = Person
        Class ca = Class.forName("反射机制.Person");
        System.out.println(ca);//ca = Person
    }
    /**
     * 如何获取Class的实例,方法有四种
     *其一:调用类本身的.class属性
     *其二:通过运行时类的对象获取,使用getClass()
     *其三:通过Class的静态方法获取
     *其四:(了解)通过类的加载器
     * @throws ClassNotFoundException 
     */
    @Test
    public void test4() throws ClassNotFoundException{
        //方法一
        Class clas1 = Person.class;
        System.out.println("方法一:"+clas1.getName());
        Class clas2 = String.class;
        System.out.println("方法一:"+clas2.getName());
        //方法二
        Person p = new Person();
        Class clas3 = p.getClass();
        System.out.println("方法二:"+clas3.getName());
        //方法三
        Class clas4 = Class.forName("反射机制.Person");
        System.out.println("方法三:"+clas4.getName());
        //方法四
        ClassLoader cl = this.getClass().getClassLoader();
        Class clas5 = cl.loadClass("反射机制.Person");
        System.out.println("方法四:"+clas5.getName());
    }
    /**
     * 类加载器:是用来将类加载进内存的,JVM规范定义了两种类加载器:启动加载器和用户自定义加载器。JVM在运行时会产生
     *三个类加载器组成初始化类加载器层次结构:依次为
     *1.引导类加载器:用C++编写是JVM自带的类加载器,负责java平台的核心库,用来加载核心类库,给加载器无法直接获取
     *2.扩展类加载器:负责jre/lib/ext目录下的jar包或-D java.ext.dirs指定目录下的jar包装入工作库
     *3.系统类加载器:负责java-classpath或-D java.class.path所指的目录下的类与jar包装入工作,是最常用的加载器
     *
     *Bootstrap ClassLoader——>Extension ClassLoader——>System ClassLoader
     */
    @Test
    public void test5(){
        ClassLoader cl1 = ClassLoader.getSystemClassLoader();
        System.out.println(cl1);        //系统加载器

        ClassLoader cl2 = cl1.getParent();
        System.out.println(cl2);        //扩展加载器

        ClassLoader cl3 = cl2.getParent();
        System.out.println(cl3);        //引导加载器

        Class clas6 = Person.class;
        ClassLoader cl4 = clas6.getClassLoader();
        System.out.println(cl4);
    }


}
原文地址:https://www.cnblogs.com/tengpengfei/p/10453998.html