Transfer from: https://thinkwon.blog.csdn.net/article/details/100128361
table of Contents
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也是如此。