full solution of reflection

Reflection overview

The JAVA reflection mechanism is that in the running state, for any class, you can know all the properties and methods of the class; for any object, you can call any of its methods and properties; this dynamically obtained information and dynamic call The function of the method of the object is called the reflection mechanism of the java language.

To dissect a class, you must first obtain the bytecode file object of the class. The anatomy uses the methods in the Class class. So first get the Class type object corresponding to each bytecode file.

What is reflection
metadata (metadata): description data describing data
Reflection : the process of obtaining metadata of a class
At runtime, dynamically obtain member information (constructor, method, field, inner class, interface) in a class , parent class, etc.)
and describe each member of the class as a new class.
Class: Represents all classes
Constructor: Represents all constructors
Method: Represents all methods
Field: Represents all fields
write picture description here

Four ways to get a Class instance

    /**
     * 1. getCLass 和 .class 出现的时期不同:Class.forName()和getClass()是在运行时加载;
     * Class.class是在编译器加载,即.class是静态加载,.getClass()是动态加载
     * 
     * 2. 除内部类外的其他类的应用上.class功能完全等于.getClass()!只是一个是用类直接获得的,
     * 一个是用实例获得的
     * 
     * java.lang.Class : 是反射的源头
     * 我们创建了一个类, 通过编译(javac.exe), 生成了对应的 .class文件, 之后我们使用 java.exe 
     * 加载(JVM 的类加载器完成)此 .class 文件, 此 .class 文件加载到内存后, 就是一个运行时类,存
     * 在缓冲区,那么这个运行时类本身就是一个 Class 实例. 
     * 1. 一个运行时类只被加载一次
     * 2. 有了 Class 的实例以后, 我们才可以进行如下的操作,
     *      1). 创建对应的运行时类的对象
     *      2). 获取对应运行时类的完整结构(属性,方法,构造器,内部类,父类,异常,所在包,注解...)
     *      3). 调用对应的运行时类的指定结构(属性,方法,构造器)
     *      4). 反射的应用 ---> 动态代理
     */

    /**
     * 如何获取运行时类的实例(4种)
     * @throws ClassNotFoundException 
     */
    @Test
    public void test2() throws ClassNotFoundException {

        //1. 调用运行时类本身的 .class 属性
        Class<Person> clazz1 = Person.class;
        System.out.println(clazz1.getName());

        //2. 通过运行时类的对象获取
        Person p = new Person();
        Class clazz2 = p.getClass();
        System.out.println(clazz2);


        //3. 通过 Class 的静态方法获取
        String className = "com.anqi.refection.test.Person";
        Class clazz3 = Class.forName(className);
        System.out.println(clazz3);

        //4. 通过类的加载器
        ClassLoader classLoader = this.getClass().getClassLoader();
        Class clazz4 = classLoader.loadClass(className);
        System.out.println(clazz4.getName());
    }

ClassLoader

    The virtual machine loads the data describing the class from the Class file into the memory, and verifies, converts, parses and initializes the data, and finally forms a Java type that can be directly used by the virtual machine. This is the class loading mechanism of the Java virtual machine.

[Three class loaders]

1. BootStrap ClassLoader : Called the bootstrap class loader, it is the top class loader in the Java class loading hierarchy, responsible for loading the core class libraries in the JDK, such as: rt.jar, resources.jar, charsets.jar, etc. Obtain from where the relevant jar or class file is loaded by the class loader through the following procedure:
2. Extension ClassLoader : called the extension class loader, responsible for loading the Java extension class library, by default loading JAVA_HOME/jre/lib/ext/ All current jars.
3. App ClassLoader: called the system class loader, responsible for loading all jar and class files in the application classpath directory.
write picture description here

    /**
     * ClassLoader 共有三层加载器 
     * Bootstrap classLoader
     * ExtClassLoader:扩展的class loader
     * AppClassLoader:系统class loader 获取不到, JVM 用来加载核心类库 获取的时候显示为 null
     * @throws ClassNotFoundException 
     * @throws IOException 
     */
    @Test
    public void test3() throws ClassNotFoundException, IOException {
        ClassLoader loader1 = ClassLoader.getSystemClassLoader();
        System.out.println(loader1);

        ClassLoader loader2 = loader1.getParent();
        System.out.println(loader2);

        ClassLoader loader3 = loader2.getParent();
        System.out.println(loader3);//null

        Class clazz = Person.class;
        ClassLoader loader4 = clazz.getClassLoader();
        System.out.println(loader4);

        String className = "java.lang.Object";
        Class clazz2 = Class.forName(className);
        ClassLoader loader5 = clazz2.getClassLoader();
        System.out.println(loader5);//null

        //应用: 加载文件
//      ClassLoader loader6 = this.getClass().getClassLoader();
//      InputStream in = 
//          loader6.getSystemResourceAsStream("db.properties");
//      Properties properties = new Properties();
//      properties.load(in);
//      String user = properties.getProperty("user");
//      String password = properties.getProperty("password");
//      System.out.println("user-"+user+"password-"+password);


        FileInputStream in = new FileInputStream(new File("‪db.properties"));
        Properties pro = new Properties();
        pro.load(in);
        String user = pro.getProperty("user");
        String password = pro.getProperty("password");
        System.out.println("user-"+user+"password-"+password);

    }

Field complete solution

    /**
     * Field -getgetDeclaredField(String name)
     *          获取指定 name 值的字段
     *       -getField(String name)
     *          获取指定 name 值的非 private 修饰的字段值
     *       -getFields()
     *          获取所有的字段,必须所有字段都不能被 private 修饰
     *       -getDeclaredFields()
     *          获取所有的字段
     *      -对 private 修饰的字段修改时,需要设置
     *          f1.setAccessible(true);压制修饰检查
     */
    //测试对应的运行时类的属性
    @Test
    public void test1() {
        Class clazz = Person.class;
        //1. getFields(): 只能获取到运行时"类中及其父类中"声明为 public 的属性
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }

        //2. getDeclareFields(): 获取运行时类"本类"声明的所有属性
        Field[] fields2 = clazz.getDeclaredFields();
        for (Field field : fields2) {
            System.out.println(field.getName());
        }
    }

    //权限修饰符 变量类型 变量名
    //获取属性的各个部分的内容
    @Test
    public void test2() {
        Class clazz = Person.class;
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            //1. 获取每个属性的权限修饰符
            int i = field.getModifiers();
            //把修饰符标识码转化成字符串
            String str1 = Modifier.toString(i);
            System.out.println(str1);
            //2. 获取属性的变量类型
            Class type = field.getType();
            System.out.println(type.getTypeName());
            //3. 获取属性名
            System.out.println(field.getName());
        }
    }

    //调用运行时类中指定的属性
    @Test
    public void test3() throws Exception {
        Class<Person> clazz = Person.class;
        //1. 获取指定的属性
        //getField(String fieldName):获取运行时类中声明为 public 的指定属性名为 fieldName 的属性
        Field name = clazz.getField("name");
        //2. 创建运行时类的对象
        Person p = (Person)clazz.newInstance();
        //3. 将运行时类的指定的属性赋值
        name.set(p, "Angel");
        System.out.println(p);

        //getDeclaredFiled(String fieldName):获取运行时类中指定的名为 fieldName 的属性
        Field age = clazz.getDeclaredField("age");
        //由于属性权限修饰符的限制, 为了保证可以给属性赋值, 需要在操作前使得该属性可以被操作。
        age.setAccessible(true);
        age.set(p, 21);
        System.out.println(p);

    }

Method full solution

    @Test
    public void test1() {

        Class clazz = Person.class;
        //1. getMethods() 获取运行时类及其父类中所有声明为 public 的方法
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            //System.out.println(method);
        }

        Method[] methods2 = clazz.getDeclaredMethods();
        for (Method method : methods2) {
            System.out.println(method);
        }
    }

    //注解 权限修饰符 返回值类型 形参列表 异常
    @Test
    public void test2() {
        Class clazz = Person.class;

        Method[] m = clazz.getDeclaredMethods();
        for (Method method : m) {
            //1.注解
            Annotation[] ann = method.getAnnotations();
            for (Annotation annotation : ann) {
                System.out.println(annotation);
            }

            //2.权限修饰符
            String str = Modifier.toString(method.getModifiers());
            System.out.print(str+" ");
            //3.返回值类型
            Class returnType = method.getReturnType();
            System.out.print(returnType.getName()+" ");
            //4.方法名
            System.out.print(method.getName());

            //5.形参列表
            Class[] para = method.getParameterTypes();
            for (Class p : para) {
                System.out.print("(");
                System.out.print(p);
                System.out.print(")");
            }

            //6. 异常类型
            Class[] exps = method.getExceptionTypes();
            if(exps.length != 0)
                System.out.println("throws ");
            for (Class exp : exps) {
                System.out.println(exp.getName());
            }
        }
    }

    //调用运行时类中指定的方法
    @Test
    public void test3() throws Exception {
        Class<Person> clazz = Person.class;
        //getMethod(String methodName, Class...params):获取运行时类中声明为 public 的方法
        Method m1 = clazz.getMethod("show");
        Person p = clazz.newInstance();
        //调用指定的方法:Object invoke(Object obj,Object...obj)
        Object returnVal = m1.invoke(p);//我是一个人
        System.out.println(returnVal);//没有返回值,所以是null

        Method m2 = clazz.getMethod("toString");
        Object returnVal1 = m2.invoke(p);
        System.out.println(returnVal1);

        //对于运行时类中静态方法的调用
        Method m3 = clazz.getMethod("info");
        m3.invoke(Person.class);

        //getDeclaredMethod(String methodName, Class...params):获取运行类中指定的方法
        Method m4 = clazz.getDeclaredMethod("display",String.class);
        m4.setAccessible(true);
        m4.invoke(p, "CHN");


    }

Constructor constructor full solution

    @Test
    public void test1() throws Exception {

        Class<Person> clazz = (Class<Person>) 
        Class.forName("com.anqi.refection.test.Person");
        //创建对应的运行时类的对象, 使用 newInstance(), 实际上就是调用了运行时类的空参构造器
        //要想能够创建成功, ① 要求对应的运行时类要有空参的构造器, ② 构造器的权限修饰符范围要大
        Person p = clazz.newInstance();
        System.out.println(p);

    }

    @Test
    public void test2() throws ClassNotFoundException {

        String className = "com.anqi.refection.test.Person";
        Class<Person> clazz = (Class<Person>) Class.forName(className);
        //获取所有 public 修饰的构造器
        Constructor[] cons =  clazz.getConstructors();
        for (Constructor constructor : cons) {
            System.out.println(constructor);
        }
    }

    //调用指定的构造器, 床架运行时类的对象
    @Test
    public void test3() throws Exception{
        Class<Person> clazz = Person.class;

        Constructor<Person> con = clazz.getDeclaredConstructor(String.class, int.class);
        con.setAccessible(true);
        Person p = con.newInstance("LiChen",18);
        System.out.println(p);
    }

Obtain parent classes, generics, interfaces, annotations, packages, etc. through reflection

    /**
     * 获取运行时类的父类
     */
    @Test
    public void test() {
        Class<Person> clazz = Person.class;
        Class superClass = clazz.getSuperclass();
        System.out.println(superClass);
    }

    /**
     * 获取带泛型的父类
     */
    @Test
    public void test2() {
        Class<Person> clazz = Person.class;
        Type type  = clazz.getGenericSuperclass();
        System.out.println(type);
        //com.anqi.refection.test.Creature<java.lang.String>
    }

    /**
     * 获取父类的泛型
     */
    @Test
    public void test3() {
        Class<Person> clazz = Person.class;
        Type type = clazz.getGenericSuperclass();
        ParameterizedType t = (ParameterizedType) type;
        Type[] types = t.getActualTypeArguments();
        System.out.println(types[0]);
        //class java.lang.String
    } 

    /**
     * 获取实现的接口
     */
    @Test
    public void test4() {
        Class<Person> clazz = Person.class;
        Class[] interfaces = clazz.getInterfaces();
        for (Class class1 : interfaces) {
            System.out.println(class1.getName());
        }
    }

    /**
     * 获取所在的包
     */
    @Test
    public void test5() {
        Class<Person> clazz = Person.class;
        Package p = clazz.getPackage();
        System.out.println(p);
    }

    /**
     * 获取注解
     */
    @Test
    public void test6() {
        Class<Person> clazz = Person.class;
        Annotation[] ann = clazz.getAnnotations();
        for (Annotation annotation : ann) {
            System.out.println(annotation);
        }
    }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325687788&siteId=291194637