阅读反射文档
This commit is contained in:
187
java se/反射.md
Normal file
187
java se/反射.md
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
# 反射
|
||||||
|
## Class对象
|
||||||
|
Class对象用于访问类信息,想要获取class对象,可以通过如下方法
|
||||||
|
### 获取Class对象方法
|
||||||
|
#### 调用实例的getClass方法
|
||||||
|
```java
|
||||||
|
Random generator = new Random():
|
||||||
|
Class cl = generator . getClass () ;
|
||||||
|
String name = cl.getName() ; // name is set to "java . util . Random"
|
||||||
|
```
|
||||||
|
#### 调用Class类的静态方法forName方法
|
||||||
|
```java
|
||||||
|
String dassName = " java . util . Random" ;
|
||||||
|
Class cl = Class.forName ( dassName ) ;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 通过T.class获取
|
||||||
|
如果T是一个java类型,那么T.class代表T类型对应的Class对象
|
||||||
|
```java
|
||||||
|
Class dl = Random.class;
|
||||||
|
Gass cl 2 = int.class ;
|
||||||
|
Class cl 3 = Double[].class ;
|
||||||
|
```
|
||||||
|
Class对象表示的是一个类型,而类型不一定是类,也包含基本类型,如int,long等。
|
||||||
|
|
||||||
|
### Class对象的比较
|
||||||
|
JVM为每个类型只维护一个Class对象,故而不同的Class之间可以通过`==`符号进行比较
|
||||||
|
```java
|
||||||
|
if(e.getClass()==Employee.class)
|
||||||
|
```
|
||||||
|
### 通过Class对象创建新实例
|
||||||
|
下述示例创建了一个与e具有相同类型的实例,newInstance方法默认会调用默认构造函数,如果该类型没有默认构造函数,会抛出一个checked exception
|
||||||
|
```java
|
||||||
|
e.getClass().newInstance()
|
||||||
|
```
|
||||||
|
如果将forName和newInstance方法结合起来使用,可以根据存储在字符串中的类型动态创建一个对象:
|
||||||
|
```java
|
||||||
|
String driverClassName = "com.mysql.cj.jdbc.Driver";
|
||||||
|
Class.forName(driverClassName).newInstance();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用反射分析类
|
||||||
|
java.lang.reflect类中含有三个类:
|
||||||
|
- Field:用于描述类的域
|
||||||
|
- Method:用于描述类的方法
|
||||||
|
- Constructor:用于描述类的构造器
|
||||||
|
|
||||||
|
### Field.getType
|
||||||
|
Field类有一个getType方法,返回值是域所属类型的Class对象。
|
||||||
|
### 获取类的域、方法和构造器
|
||||||
|
#### Class.getFields
|
||||||
|
返回值为类的public域,包含从父类继承的public域
|
||||||
|
#### Class.getDeclaredFields
|
||||||
|
返回类中声明的所有域,包含为private和protected的域,但是不包含从父类继承的域
|
||||||
|
#### Class.getMethods
|
||||||
|
返回值为类提供的public方法,包含从父类继承的public方法
|
||||||
|
#### Class.getDeclaredMethods
|
||||||
|
返回类中声明的所有方法,包含private方法和protected方法,但是不包含从父类继承的方法
|
||||||
|
#### Class.getConstructors
|
||||||
|
只能获取到public构造器
|
||||||
|
#### Class.getDeclaredConstructors
|
||||||
|
能获取到所有的构造器,包含private和protected构造器
|
||||||
|
### Method、Field、Constructor中的方法
|
||||||
|
#### getDeclaringClass
|
||||||
|
返回定义该方法、域、构造器类型的Class对象
|
||||||
|
```java
|
||||||
|
Class getDeclaringClass()
|
||||||
|
```
|
||||||
|
#### getExceptionTypes(Method和Constructor中包含)
|
||||||
|
返回方法抛出的异常类型的数组
|
||||||
|
```java
|
||||||
|
Class[] getExceptionTypes()
|
||||||
|
```
|
||||||
|
#### getModifiers
|
||||||
|
返回一个描述Field、Method、Constrcutor的修饰符的整数类型(不同的位描述不同的修饰符状态,如public、static、是否抽象类、是否接口等)
|
||||||
|
```java
|
||||||
|
int getModifiers()
|
||||||
|
```
|
||||||
|
#### getName
|
||||||
|
返回描述Field、Constructor、Method的字符串
|
||||||
|
```java
|
||||||
|
String getName()
|
||||||
|
```
|
||||||
|
#### getParameterTypes(Method和Constructor中包含)
|
||||||
|
返回一个Class数组,用于描述参数类型
|
||||||
|
```java
|
||||||
|
Class[] getParameterTypes()
|
||||||
|
```
|
||||||
|
#### getReturnType(只在Method方法中包含)
|
||||||
|
返回Method的返回类型
|
||||||
|
```java
|
||||||
|
Class getReturnType()
|
||||||
|
```
|
||||||
|
### Modifier中的方法
|
||||||
|
#### toString
|
||||||
|
该静态方法将modifiers整数中的修饰符内容转化为字符串
|
||||||
|
```java
|
||||||
|
static String toString(int modifiers)
|
||||||
|
```
|
||||||
|
#### isAbstract
|
||||||
|
```java
|
||||||
|
static boolean isAbstract(int modifiers)
|
||||||
|
```
|
||||||
|
#### isFinal
|
||||||
|
```java
|
||||||
|
static boolean isFinal(int modifiers)
|
||||||
|
```
|
||||||
|
#### isInterface
|
||||||
|
```java
|
||||||
|
static boolean isInterface(int modifiers)
|
||||||
|
```
|
||||||
|
#### isNative
|
||||||
|
```java
|
||||||
|
static boolean isNative(int modifiers)
|
||||||
|
```
|
||||||
|
#### isPrivate
|
||||||
|
```java
|
||||||
|
static boolean isPrivate(int modifiers)
|
||||||
|
```
|
||||||
|
#### isProtected
|
||||||
|
```java
|
||||||
|
static boolean isProtected(int modifiers)
|
||||||
|
```
|
||||||
|
#### isPublic
|
||||||
|
```java
|
||||||
|
static boolean isPublic(int modifiers)
|
||||||
|
```
|
||||||
|
#### isStatic
|
||||||
|
```java
|
||||||
|
static boolean isStatic(int modifiers)
|
||||||
|
```
|
||||||
|
#### isSynchronized
|
||||||
|
```java
|
||||||
|
static boolean isSynchronized(int modifiers)
|
||||||
|
```
|
||||||
|
#### isVolatile
|
||||||
|
```java
|
||||||
|
static boolean isVolatile(int modifiers)
|
||||||
|
```
|
||||||
|
## 使用反射分析类的内容
|
||||||
|
如果在运行时有一个Field对象和一个类实例obj,想要查看obj实例中Field对应域的值,可以使用如下方式:
|
||||||
|
```java
|
||||||
|
f.get(obj);
|
||||||
|
```
|
||||||
|
但是,如果Field的modifiers显示该Field是private的,那么`f.get(obj)`方法将会抛出一个IllegalAccessException。
|
||||||
|
此时,可以通过`f.setAccessible(true)`来访问private域中的内容。
|
||||||
|
```java
|
||||||
|
f.setAccessible(true);
|
||||||
|
Object v = f.get(obj);
|
||||||
|
```
|
||||||
|
设置Field的值则是可以通过`f.set(obj,value)`来实现。
|
||||||
|
```java
|
||||||
|
f.setAccessible(true);
|
||||||
|
f.setValue(obj,"shiro");
|
||||||
|
```
|
||||||
|
### AccessibleObject
|
||||||
|
Field,Method,Constructor类型都拥有公共的父类AccessibleObject
|
||||||
|
#### setAccessible
|
||||||
|
```java
|
||||||
|
void setAccessible(boolean flag);
|
||||||
|
|
||||||
|
// 批量设置可访问状态
|
||||||
|
static void setAccessible(AccessibleObject[] array,boolean flag);
|
||||||
|
```
|
||||||
|
#### isAccessible
|
||||||
|
```java
|
||||||
|
boolean isAccessible();
|
||||||
|
```
|
||||||
|
## 使用反射调用方法
|
||||||
|
Method类中提供了一个invoke方法来调用Method所表示的方法,`Method.invoke`方法签名如下:
|
||||||
|
```java
|
||||||
|
Object invoke(Object obj,Object... args)
|
||||||
|
```
|
||||||
|
obj表示调用方法的对象,args表示参数数组。
|
||||||
|
> 如果Method位静态方法,那么obj应该传入null
|
||||||
|
|
||||||
|
如果Method代表的方法返回的是一个基本类型,那么invoke方法会返回器包装类型,如`int->Integer`.
|
||||||
|
### Method.getMethod
|
||||||
|
如果想要根据方法名称和参数类型来获取Class对象中的Method,可以调用如下方法:
|
||||||
|
```java
|
||||||
|
Method getMethod(String name,Class... parameterTypes)
|
||||||
|
```
|
||||||
|
示例如下:
|
||||||
|
```java
|
||||||
|
Method ml = Employee. class.getMethod ( "getName") ;
|
||||||
|
Method m2 = Employee.class.getMethod ( "raiseSalary" , double.class) ;
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user