JavaEE basics (two) Java reflection

Transfer from: https://thinkwon.blog.csdn.net/article/details/100128361

definition

The Java reflection mechanism is in the running state, for any class, you can know all the properties and methods of this class; for any object, you can call any of its methods and properties. The function of dynamically obtaining information and dynamically calling object methods is called the reflection mechanism of Java language.

use

Through reflection, Java code can discover information about the fields, methods, and constructors of the loaded class, and can operate on these fields, methods, and constructors within security restrictions.

Many people think that reflection is not widely used in actual Java development and application, but it is not. When we are using an IDE (such as IDEA/Eclipse), when we input an object or class and call its properties and methods, press the (".") dot, and the compiler will automatically list her properties or Method, reflection will be used here.

The most important use of reflection is to develop various general frameworks

Many frameworks (such as Spring) are configurable (such as Spring loads Beans through XML configuration mode). In order to ensure the universality of the framework, they may load different objects or classes and call different methods according to the configuration file. Use reflection-dynamically load objects that need to be loaded at runtime.

For framework developers, reflection is very useful, and it is the core of various container implementations. For the average developer, there will be less use of reflection without going deep into the framework. However, understanding the underlying mechanism of the framework can help enrich their programming ideas and is also very beneficial.

The Java reflection framework provides the following functions:

  • Determine the class of any object at runtime
  • Construct an object of any class at runtime
  • Determine the member variables and methods of any class at runtime
  • Call any object's method at runtime

Pros and cons of reflection

Advantages of reflection

Using the reflection mechanism, the code can be assembled at runtime, which improves the flexibility and scalability of the program, reduces coupling, and improves adaptive capabilities. It allows the program to create and control objects of any class without hard coding the target class

Disadvantages of reflection

  • Performance issues: The use of reflection is basically an interpretation operation, and the JVM cannot optimize these codes. Therefore, the efficiency of reflection operations is much lower than those of non-reflection operations. The reflection mechanism is mainly used in system frameworks that require high flexibility and scalability. It is not recommended to use in programs that require high performance

  • Security restrictions: The use of reflection technology requires the program to be run in an environment without security restrictions

  • Internal exposure: Since reflection allows the code to perform some operations that are not allowed under normal circumstances (such as accessing private properties and methods), the use of reflection may cause unexpected side effects-the code has functional errors, reducing the risk Portability. Reflective code destroys abstraction, so when the platform changes, the behavior of the code may also change.

Related classes of reflection mechanism

The classes related to Java reflection are as follows:

Class name use
Class class The entity representing the class, representing the class and interface in the running Java application
Field class Member variables representing the class (member variables are also called attributes of the class)
Method class Representative class method
Constructor class Representative class construction method

Class class

Class represents the entity of the class and represents the class and interface in the running Java application. A lot of useful methods are provided in this class. Here is a brief introduction to them.

  • Get class related methods
method use
asSubclass(Class clazz) Convert the object of the passed class into an object representing its subclass
Cast Convert objects into objects representing classes or interfaces
getClassLoader() Get class loader
getClasses() Returns an array containing all public and interface objects of the class
getDeclaredClasses() Returns an array, the array contains objects of all classes and interface classes in this class
forName (String className) Returns the object of the class based on the class name
getName() Get the full path name of the class
newInstance() Create an instance of the class
getPackage() Get class package
getSimpleName() Get the name of the class
getSuperclass() Get the name of the parent class inherited by the current class
getInterfaces () Get the class or interface implemented by the current class
  • Get methods related to attributes in the class
method use
getField(String name) Obtain a public property object
getFields() Get all public property objects
getDeclaredField(String name) Get an attribute object
getDeclaredFields() Get all attribute objects
  • Get the methods related to the constructor in the class
method use
getConstructor(Class…<?> parameterTypes) Get the public construction method matching the parameter type in this class
getConstructors() Get all public construction methods of this class
getDeclaredConstructor(Class…<?> parameterTypes) Get the construction method that matches the parameter type in this class
getDeclaredConstructors() Get all the construction methods of this class
  • Get methods related to methods in the class
method use
getMethod(String name, Class…<?> parameterTypes) Obtain a public method of this class
getMethods() Get all public methods of this class
getDeclaredMethod(String name, Class…<?> parameterTypes) Get a method of this class
getDeclaredMethods() Get all methods of this class
  • Other important methods in the class
method use
isAnnotation() Returns true if it is an annotation type
isAnnotationPresent(Class<? extends Annotation> annotationClass) Returns true if it is the specified type annotation type
isAnonymousClass() Return true if it is an anonymous class
isArray() Return true if it is an array class
isEnum () Returns true if it is an enum
isInstance(Object obj) Return true if obj is an instance of this class
isInterface() Return true if it is an interface class
isLocalClass() Return true if it is a local class
isMemberClass () Returns true if it is an inner class

Field class

Field represents the member variables of the class (member variables are also called attributes of the class).

method Method purpose
equals(Object obj) 属性与obj相等则返回true
get(Object obj) 获得obj中对应的属性值
set(Object obj, Object value) 设置obj中对应属性值

Method类

Method代表类的方法。

方法 方法 用途
invoke(Object obj, Object… args) 传递object对象及参数调用该对象对应的方法

Constructor类

Constructor代表类的构造方法。

方法 方法 用途
newInstance(Object… initargs) 根据传递的参数创建类的对象

示例

为了演示反射的使用,首先构造一个与书籍相关的model——Book.java,然后了解获取Class类对象的三种方法,最后通过反射方法示例创建对象、反射私有构造方法、反射私有属性、反射私有方法

被反射类Book.java

public class Book{
    
    
    private final static String TAG = "BookTag";

    private String name;
    private String author;

    @Override
    public String toString() {
    
    
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                '}';
    }

    public Book() {
    
    
    }

    private Book(String name, String author) {
    
    
        this.name = name;
        this.author = author;
    }

    public String getName() {
    
    
        return name;
    }

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

    public String getAuthor() {
    
    
        return author;
    }

    public void setAuthor(String author) {
    
    
        this.author = author;
    }

    private String declaredMethod(int index) {
    
    
        String string = null;
        switch (index) {
    
    
            case 0:
                string = "I am declaredMethod 0 !";
                break;
            case 1:
                string = "I am declaredMethod 1 !";
                break;
            default:
                string = "I am declaredMethod -1 !";
        }

        return string;
    }
}

获取Class类对象的三种方法

在反射中,要获取一个类或调用一个类的方法,我们首先需要获取到该类的 Class 对象。
在 Java API 中,获取 Class 类对象的三种方法

  • 方法一:使用 Class.forName 静态方法。当你知道该类的全路径名时,你可以使用该方法获取 Class 类对象。但可能抛出 ClassNotFoundException 异常
    Class<?> classBook = Class.forName(“com.jourwon.reflect.Book”);

  • 方法二:这种方法只适合在编译前就知道操作的 Class。直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高,这说明任何一个类都有一个隐含的静态成员变量 class
    Class clz = Book.class;

  • 方法三:使用类对象的 getClass() 方法。
    Book book1 = new Book();
    Class<? extends Book> book1Class = book1.getClass();

@Test
public void getClz() {
    
    
    try {
    
    
        // 方法一,使用 Class.forName 静态方法
        Class<?> classBook = Class.forName("com.jourwon.reflect.Book");

        // 方法二:直接通过 类名.class 的方式得到
        Class clz = Book.class;

        // 方法三:使用类对象的 getClass() 方法。
        Book book1 = new Book();
        Class<? extends Book> book1Class = book1.getClass();

        System.out.println(classBook == clz);
        System.out.println(classBook == book1Class);

    } catch (Exception ex) {
    
    
        ex.printStackTrace();
    }
}

输出结果都是true,可以知道三种方法获取到的Class对象都是同一个对象

反射常用类和方法测试

public class ReflectClass {
    
    

    private static final Logger log = LoggerFactory.getLogger(ReflectClass.class);

    // 创建对象
    @Test
    public void reflectNewInstance() {
    
    
        try {
    
    
            Class<?> classBook = Class.forName("com.jourwon.reflect.Book");

            Object objectBook = classBook.newInstance();
            Book book = (Book) objectBook;
            book.setName("Java高级特性-反射-创建对象");
            book.setAuthor("JourWon");
            log.info(book.toString());

        } catch (Exception ex) {
    
    
            ex.printStackTrace();
        }
    }

    // 反射私有的构造方法
    @Test
    public void reflectPrivateConstructor() {
    
    
        try {
    
    
            Class<?> classBook = Class.forName("com.jourwon.reflect.Book");
            Constructor<?> declaredConstructorBook = classBook.getDeclaredConstructor(String.class, String.class);
            // 暴力反射
            declaredConstructorBook.setAccessible(true);
            Object objectBook = declaredConstructorBook.newInstance("Java高级特性-反射-反射私有的构造方法", "JourWon");
            Book book = (Book) objectBook;
            log.info(book.toString());
        } catch (Exception ex) {
    
    
            ex.printStackTrace();
        }
    }

    // 反射私有属性
    @Test
    public void reflectPrivateField() {
    
    
        try {
    
    
            Class<?> classBook = Class.forName("com.jourwon.reflect.Book");
            Object objectBook = classBook.newInstance();
            Field fieldTag = classBook.getDeclaredField("TAG");
            fieldTag.setAccessible(true);
            String tag = (String) fieldTag.get(objectBook);
            log.info(tag);
        } catch (Exception ex) {
    
    
            ex.printStackTrace();
        }
    }


    // 反射私有方法
    @Test
    public void reflectPrivateMethod() {
    
    
        try {
    
    
            Class<?> classBook = Class.forName("com.jourwon.reflect.Book");
            Method methodBook = classBook.getDeclaredMethod("declaredMethod", int.class);
            methodBook.setAccessible(true);
            Object objectBook = classBook.newInstance();
            String string = (String) methodBook.invoke(objectBook, 0);

            ReflectClass.

            log.info(string);
        } catch (Exception ex) {
    
    
            ex.printStackTrace();
        }
    }


}

输出结果

[main] INFO com.jourwon.reflect.ReflectClass - Book{
    
    name='Java高级特性-反射-创建对象', author='JourWon'}

[main] INFO com.jourwon.reflect.ReflectClass - Book{
    
    name='Java高级特性-反射-反射私有的构造方法', author='JourWon'}

[main] INFO com.jourwon.reflect.ReflectClass - BookTag

[main] INFO com.jourwon.reflect.ReflectClass - I am declaredMethod 0 ! 

通过反射获取私有属性,方法和构造方法时,需要进行暴力反射,设置setAccessible(true)。否则会报错说无法获取私有属性,方法和构造方法

总结

本文列举了反射机制使用过程中常用的、重要的一些类及其方法,更多信息和用法,反射原理和源码分析需要近一步的阅读反射相关资料。

在阅读Class类文档时发现一个特点,以通过反射获得Method对象为例,一般会提供四种方法,getMethod(parameterTypes)、getMethods()、getDeclaredMethod(parameterTypes)和getDeclaredMethods()。getMethod(parameterTypes)用来获取某个公有的方法的对象,getMethods()获得该类所有公有的方法,getDeclaredMethod(parameterTypes)获得该类某个方法,getDeclaredMethods()获得该类所有方法。带有Declared修饰的方法可以反射到私有的方法,没有Declared修饰的只能用来反射公有的方法。其他的Annotation、Field、Constructor也是如此。

Guess you like

Origin blog.csdn.net/jinian2016/article/details/108306947