Java Reflect

Reflection

1. Overview of java reflection mechanism

Reflection mechanism allows the program to obtain the internal information of any class with the help of reflection API during execution, and annotate and operate the internal properties and methods of any object

Class c = Class.forName("java.lang.String");

After loading the class, the method area of the heap memory generates a class object (a class has only one class object), which contains complete radar structure information. We can see the class structure through this object. This object is like a mirror, through which we can see the class structure, so we call it "reflection"

advantage

shortcoming

Main APIs for reflection

package com.wang.reflection;

//什么叫反射
public class test02 {
    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获得类的Class对象
        Class c1 = Class.forName("com.wang.reflection.User");
        System.out.println(c1);

        Class c2 = Class.forName("com.wang.reflection.User");
        Class c3 = Class.forName("com.wang.reflection.User");
        Class c4 = Class.forName("com.wang.reflection.User");

        //一个类在内存中只有一个Class对象
        //Class类:描述类的类,所有类的父类
        //一个类被加载后,类的整个结构都被封装在Class对象中
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());
    }
}

//实体类:pojo或entity
class User {
    private String name;
    private int id;
    private int age;

    public User() {
    }

    public User(String name,int id,int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ",id=" + id +
                ",age=" + age +
                '}';
    }
}

2. Class

1. Class introduction

For each class, the JRE retains an object of the same class type. A class object contains information about a specific structure (class / interface / enum / annotation / primitive type / void / [])

2. Get the instance of class

3. Which types can have class objects

package com.wang.reflection;

import java.lang.annotation.ElementType;

//所有类型的Class
public class test04 {
    public static void main(String[] args) {
        Class c1 = Object.class;        //类
        Class c2 = Comparable.class;    //接口
        Class c3 = String[].class;      //一维数组
        Class c4 = int[][].class;       //二维数组
        Class c5 = Override.class;      //注解
        Class c6 = ElementType.class;   //枚举类型
        Class c7 = Integer.class;       //基本数据类型
        Class c8 = void.class;          //void
        Class c9 = Class.class;         //Class

        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);

        //只要元素类型与维度一样,就是同一个Class
        int[] a = new int[10];
        int[] b = new int[100];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());
    }
}

3. JAVA memory analysis

4. Class loading process

When a program actively uses a class, if the class has not been loaded into memory, the system will initialize the class through the following three steps

1. Class loading

Read the class file of the class into memory and create a Java Lang.class object This is done by the class loader

2. Class link

Merge the binary data of the class into the JRE

3. Class initialization

The JVM is responsible for initializing classes

4. Specific analysis

package com.wang.reflection;

public class test05 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(A.m);

        /*
        1.加载到内存,会产生一个类对应的Class对象
        2.链接,链接结束后m被初始化为0
        3.初始化
            <clinit>(){
                   System.out.println("A类静态代码块初始化");
                   m = 300;
                   m = 100;
                   }
             合并静态代码(static)
             合并静态代码的顺序遵循写代码时的顺序
             此时m=100
         */
    }
}
/*
静态代码块优先于构造块执行
构造块优先于方法调用执行
 */
class A {
    
    static {
        System.out.println("A类静态代码块初始化");
        m = 300;
    }

    static int m = 100;

    public A() {
        System.out.println("A类的无参构造初始化");
    }
}

Focus on understanding static loading!

5. Initialization of analysis class

1. Active reference of class (class initialization must occur)

2. Passive reference of class (class initialization will not occur)

package com.wang.reflection;

import java.sql.sqlOutput;

//测试类什么时候会初始化
public class test06 {

    static {
        System.out.println("Main类被加载");
    }

    public static void main(String[] args) throws ClassNotFoundException {
        //1.主动引用:先初始化父类再初始化子类(当虚拟机启动,先初始化main方法所在的类)
        //Son son = new Son();

        //2.反射也会产生主动引用
        //Class.forName("com.wang.reflection.son");

        //不会产生类的引用的方法:子类调用父类的静态变量,不会导致子类被初始化
        //System.out.println(Son.b);

        //通过数组定义类引用,不会触发此类的初始化
        //Son[] array = new Son[5];

        //引用常量(final)不会触发此类的初始化
        System.out.println(Son.M);

    }

}

class Father {

    static int b = 2;

    static {
        System.out.println("父类被加载");
    }
}

class Son extends Father {

    static {
        System.out.println("子类被加载");
        m = 300;
    }

    static int m = 100;
    static final int M = 1;
}

6. Function of class loader

1. Function of class loader

Load the bytecode content of the class file into memory, convert the static data into the run-time data structure of the method, and then generate a Java. Net file representing this class in the heap Lang. class object, as the access entry of class data in the method area

2. Class cache

The standard Java se class loader can find classes as required. Once a class is loaded into the class loader, it will remain loaded (cached) for a period of time However, the JVM garbage collection mechanism can look back on these class objects

3. Type of class loader

The class loader is used to load classes into memory The JVM specification defines the following types of class loaders

package com.wang.reflection;

public class test07 {
    public static void main(String[] args) throws ClassNotFoundException {

        //获取系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        //获取系统类加载器的父类加载器-->扩展类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);

        //获取扩展类加载器的父类加载器-->根加载器(c/c++)
        ClassLoader parentParent = parent.getParent();
        System.out.println(parentParent);

        //测试当前类是哪个加载器加载的-->系统类加载器
        ClassLoader classLoader = Class.forName("com.wang.reflection.test07").getClassLoader();
        System.out.println(classLoader);

        //测试JDK内部类是谁加载的-->根加载器
        ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader1);

        //如何获得系统类加载器可以加载的路径

        System.out.println(System.getProperty("java.class.path"));
    }
}

7. Get the complete structure of the runtime class

Note that the getdeclaredxxx () method should be written for the private method and field

package com.wang.reflection;

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

//获取类的信息
public class test08 {
    public static void main(String[] args) throws ClassNotFoundException,NoSuchFieldException,NoSuchMethodException {
        Class c1 = Class.forName("com.wang.reflection.User");

//        User user = new User();
//        Class c1 = user.getClass();

        //获得类的名字
        System.out.println(c1.getName());       //获得包名 + 类名
        System.out.println(c1.getSimpleName()); //获得类名

        //获得类的属性
        System.out.println("==============================");
        Field[] fields = c1.getFields();    //getFields()只能找到public属性
        //fields.for    -->     遍历数组的快捷键

        fields = c1.getDeclaredFields();    //getDeclaredFields()找到全部的属性
        for (Field field : fields) {
            System.out.println(field);
        }

        //获得指定属性的值
        System.out.println("===========================");
        Field name = c1.getDeclaredField("name");
        System.out.println(name);

        //获得类的方法
        System.out.println("=======================");
        Method[] methods = c1.getmethods();     //getmethods()获得本类及其父类的public方法
        for (Method method : methods) {
            System.out.println("正常的:" + method);
        }
        methods = c1.getDeclaredMethods();      //getDeclaredMethods()获得本类的所有方法
        for (Method method : methods) {
            System.out.println("getDeclaredMethods:" + method);
        }

        //获得指定方法
        //注意,要写获得方法的参数类型,无参数则为null,否则写参数的类(参数类型.class)  ---->   这是由于Java存在重载的特性
        System.out.println("=======================");
        Method getName = c1.getmethod("getName",null);
        Method setName = c1.getmethod("setName",String.class);
        System.out.println(getName);
        System.out.println(setName);

        //获得指定的构造器
        System.out.println("=======================");
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        constructors = c1.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("#" + constructor);
        }

        //获得指定的构造器
        Constructor constructor = c1.getConstructor(String.class,int.class,int.class);
        System.out.println(constructor);

    }
}

8. Creating objects by reflection is the object operation

package com.wang.reflection;

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

//动态的创建对象,通过反射
public class test09 {
    public static void main(String[] args) throws ClassNotFoundException,illegalaccessexception,InstantiationException,NoSuchMethodException,InvocationTargetException,NoSuchFieldException {
        //获得Class对象
        Class c1 = Class.forName("com.wang.reflection.User");

//        //构造一个对象:newInstance()
//        User user = (User)c1.newInstance();     //本质上是调用了类的无参构造器
//        System.out.println(user);
//
//        //通过构造器创建对象(如果没有写无参构造器),通过已有的构造器创建
//        /*
//        先获取类对象
//        然后获取有参构造
//        通过有参构造获取对象
//         */
//        Constructor constructor = c1.getDeclaredConstructor(String.class,int.class);
//        User user2 = (User) constructor.newInstance("wang",001,18);
//        System.out.println(user2);

        //通过反射调用普通方法
        User user3 = (User)c1.newInstance();
        //通过反射获取一个方法
        Method setName = c1.getDeclaredMethod("setName",String.class);

        //invoke:激活
        //方法.invoke(对象,"方法的值")
        setName.invoke(user3,"wang");
        System.out.println(user3.getName());

        //通过反射操作属性
        System.out.println("===========================");
        User user4 = (User)c1.newInstance();
        Field name = c1.getDeclaredField("name");

        //不能直接操作私有属性,我们需要关闭程序的安全监测,通过属性或方法的setAccessible(true)
        name.setAccessible(true);
        name.set(user4,"wang_sky");
        System.out.println(user4.getName());
    }
}

setAccessible

Reflection will affect the speed of the program, and turning off safety check will improve the speed of the program

The following is the test code

package com.wang.reflection;

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

//分析性能问题
public class test10 {

    public static void main(String[] args) throws NoSuchMethodException,InvocationTargetException {
        test01();
        test02();
        test03();
    }

    //普通方式调用
    public static void test01() {
        User user = new User();

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < 1000000000; i++) {
            user.getName();
        }
        
        long endTime = System.currentTimeMillis();

        System.out.println("普通方式执行10亿次:" + (endTime - startTime) + "ms");
    }
    //反射方式调用
    public static void test02() throws NoSuchMethodException,illegalaccessexception {
        User user = new User();
        Class c1 = user.getClass();

        Method getName = c1.getDeclaredMethod("getName",null);

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user,null);
        }

        long endTime = System.currentTimeMillis();

        System.out.println("反射方式执行10亿次:" + (endTime - startTime) + "ms");
    }

    //反射方式调用,关闭安全检测
    public static void test03() throws NoSuchMethodException,null);
        getName.setAccessible(true);

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user,null);
        }

        long endTime = System.currentTimeMillis();

        System.out.println("反射方式,关闭安全检测,执行10亿次:" + (endTime - startTime) + "ms");
    }
}

result

1 billion times in ordinary way: 4ms

1 billion times in reflection mode: 2760ms

Reflection mode, 1 billion times: 1331ms

9. Reflection operation generics

package com.wang.reflection;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

//通过反射获取泛型
public class test11 {

    public void test01(Map<String,User> map,List<User> list) {
        System.out.println("test01");
    }

    public Map<String,User> test02() {
        System.out.println("test02");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = test11.class.getmethod("test01",Map.class,List.class);

        //获得参数类型
        Type[] genericParameterTypes = method.getGenericParameterTypes();

        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("#" + genericParameterType);
            //如果是泛型,执行getActualTypeArguments返回真实的类型
            if (genericParameterType instanceof ParameterizedType){
                Type[] actualTypeArguments =  ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println("*" + actualTypeArgument);
                }
            }
        }

        method = test11.class.getmethod("test02",null);
        //获得返回类型
        Type genericReturnType = method.getGenericReturnType();

        if (genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments =  ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println("*" + actualTypeArgument);
            }
        }
    }
}

10. Reflection operation notes

Getannotation() method

package com.wang.reflection;

import java.lang.annotation.*;
import java.lang.reflect.Field;

//练习反射操作注解
public class test12 {

    public static void main(String[] args) throws ClassNotFoundException,NoSuchFieldException {
        Class c1 = Class.forName("com.wang.reflection.Student2");

        //通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }

        //获得注解的value的值
        Table_wang table_wang = (Table_wang) c1.getAnnotation(Table_wang.class);
        String value = table_wang.value();
        System.out.println(value);

        //获得类指定的注解
        Field f = c1.getDeclaredField("id");
        Field_wang annotation = f.getAnnotation(Field_wang.class);
        System.out.println(annotation.colunmName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
    }



}

@Table_wang("db_Student")
class Student2 {

    @Field_wang(colunmName = "db_id",type = "int",length = 10)
    private int id;
    @Field_wang(colunmName = "db_age",length = 10)
    private int age;
    @Field_wang(colunmName = "db_name",type = "varchar",length = 3)
    private String name;

    public Student2() {
    }

    public Student2(int id,int age,String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student2{" +
                "id=" + id +
                ",age=" + age +
                ",name='" + name + '\'' +
                '}';
    }
}

//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table_wang {
    String value();
}

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field_wang {
    String colunmName();
    String type();
    int length();
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>