Java反射与注解
This commit is contained in:
parent
34e62c8740
commit
e45def4c82
@ -1,26 +1,40 @@
|
|||||||
# Java 反射
|
# Java 反射与注解
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<a href="#一Class-类">一、Class 类</a><br/>
|
||||||
|
<a href="#11-Class-对象">1.1 Class 对象</a><br/>
|
||||||
|
<a href="#12-名称信息">1.2 名称信息</a><br/>
|
||||||
|
<a href="#13-构造器">1.3 构造器</a><br/>
|
||||||
|
<a href="#14-字段信息">1.4 字段信息</a><br/>
|
||||||
|
<a href="#15-方法信息">1.5 方法信息</a><br/>
|
||||||
|
<a href="#16--类型检查">1.6 类型检查</a><br/>
|
||||||
|
<a href="#二注解">二、注解</a><br/>
|
||||||
|
<a href="#21-注解定义">2.1 注解定义</a><br/>
|
||||||
|
<a href="#22-注解信息">2.2 注解信息</a><br/>
|
||||||
|
<a href="#23-注解继承">2.3 注解继承</a><br/>
|
||||||
|
</nav>
|
||||||
|
|
||||||
## 一、Class 类
|
## 一、Class 类
|
||||||
|
|
||||||
### 1.1 Class 对象
|
### 1.1 Class 对象
|
||||||
|
|
||||||
在 Java 中,每个已加载的类在内存中都有一份类信息,类信息对应的类是 java.lang.Class,每个对象都持有指向它所属类信息的引用。所以想要获取 Class 对象,有以下三种方法:
|
在 Java 中,每个已加载的类在内存中都有一份类信息,类信息对应的类是 `java.lang.Class`,每个对象都持有指向它所属类信息的引用。所以想要获取 Class 对象,有以下三种方法:
|
||||||
|
|
||||||
+ 通过类名获取:
|
1. 通过类名获取:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
Class<Date> dateClass = Date.class;
|
Class<Date> dateClass = Date.class;
|
||||||
Class<Integer> integerClass = int.class;
|
Class<Integer> integerClass = int.class;
|
||||||
```
|
```
|
||||||
|
|
||||||
+ 通过对象的`getClass()`方法获取:
|
2. 通过对象的`getClass()`方法获取:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
Date date = new Date();
|
Date date = new Date();
|
||||||
Class<? extends Date> aClass = date.getClass();
|
Class<? extends Date> aClass = date.getClass();
|
||||||
```
|
```
|
||||||
|
|
||||||
+ 通过 Class 类的静态方法 `forName` 获取:
|
3. 通过 Class 类的静态方法 `forName` 获取:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
Class<?> aClass = Class.forName("java.util.Date");
|
Class<?> aClass = Class.forName("java.util.Date");
|
||||||
@ -43,7 +57,7 @@ Class 提供了如下三个方法,由于获取名称信息,其作用和输
|
|||||||
| String[].class | [Ljava.lang.String; | String[] | java.lang.String[] |
|
| String[].class | [Ljava.lang.String; | String[] | java.lang.String[] |
|
||||||
| ArrayList.class | java.util.ArrayList | ArrayList | java.util.ArrayList |
|
| ArrayList.class | java.util.ArrayList | ArrayList | java.util.ArrayList |
|
||||||
|
|
||||||
对于数组类型的getName返回值,使用前缀`[`表示数组,有几个`[`表示是几维数组,数组类型使用字符表示:boolean(Z)、byte(B)、char(C)、double(D)、float(F)、int(I)、long(J)、short(S)、接口和类(L)。
|
对于数组类型的getName返回值,使用前缀`[`表示数组,有几个`[`表示是几维数组,数组类型使用字符表示:`boolean(Z)`、`byte(B)`、`char(C)`、`double(D)`、`float(F)`、`int(I)`、`long(J)`、`short(S)`、`接口和类(L)`。
|
||||||
|
|
||||||
### 1.3 构造器
|
### 1.3 构造器
|
||||||
|
|
||||||
@ -60,7 +74,7 @@ public Constructor<T> getConstructor(Class<?>... parameterTypes)
|
|||||||
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
|
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
|
||||||
```
|
```
|
||||||
|
|
||||||
获取指定的构造器后,可以使用`newInstance`方法来创建其实例,实例如下:
|
获取指定的构造器后,可以使用 `newInstance` 方法来创建其实例,实例如下:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class Test {
|
class Test {
|
||||||
@ -87,7 +101,7 @@ class Test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
输出:Student{name='heibaiying', age=10}
|
// 输出:Student{name='heibaiying', age=10}
|
||||||
```
|
```
|
||||||
|
|
||||||
如果你只是想调用默认的无参构造器,则可以直接使用 Class 对象的`newInstance`方法:
|
如果你只是想调用默认的无参构造器,则可以直接使用 Class 对象的`newInstance`方法:
|
||||||
@ -146,7 +160,7 @@ class Test {
|
|||||||
System.out.println(field.get(student));
|
System.out.println(field.get(student));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
输出: heibaiying
|
// 输出: heibaiying
|
||||||
```
|
```
|
||||||
|
|
||||||
### 1.5 方法信息
|
### 1.5 方法信息
|
||||||
@ -195,12 +209,12 @@ class Test {
|
|||||||
System.out.println(geMethod.invoke(student));
|
System.out.println(geMethod.invoke(student));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
输出: heibaiying
|
// 输出: heibaiying
|
||||||
```
|
```
|
||||||
|
|
||||||
### 1.6 类型检查
|
### 1.6 类型检查
|
||||||
|
|
||||||
想要判断某个对象是否是某个类或其子类的示例,可以使用`instanceof`关键字,或者使用 Class 的 `isInstance`方法,示例如下:
|
想要判断某个对象是否是某个类或其子类的示例,可以使用 `instanceof` 关键字,或者使用 Class 的 `isInstance` 方法,示例如下:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
static class Manager {}
|
static class Manager {}
|
||||||
@ -225,7 +239,7 @@ employee.getClass().equals(Manager.class); // false
|
|||||||
employee.getClass().equals(Employee.class); // true
|
employee.getClass().equals(Employee.class); // true
|
||||||
```
|
```
|
||||||
|
|
||||||
在知道对象的类型后,如果你需要对其进行类型转换,则可以使用类型转换语法或者 Class 的`cast`方法:
|
在知道对象的类型后,如果你需要对其进行类型转换,则可以使用类型转换语法或者 Class 的 `cast` 方法:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
Manager manager01 = Manager.class.cast(employee);
|
Manager manager01 = Manager.class.cast(employee);
|
||||||
@ -238,7 +252,7 @@ Manager manager02 = (Manager) employee;
|
|||||||
|
|
||||||
### 2.1 注解定义
|
### 2.1 注解定义
|
||||||
|
|
||||||
下面是`@Override`注解的定义,所有注解均使用`@interface`关键字修饰,`@Target`定义注解的运用对象,`@Retention`表示注解信息保留到什么时候。
|
下面是 `@Override` 注解的定义,所有注解均使用 `@interface` 关键字修饰, `@Target` 定义注解的运用对象,`@Retention` 表示注解信息保留到什么时候:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
@ -247,32 +261,30 @@ public @interface Override {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`@Target`有以下可选值,其含义分别如下:
|
`@Target` 有以下可选值,其含义分别如下:
|
||||||
|
|
||||||
- **TYPE**:表示类、接口(包括注释类型)或枚举声明
|
- **TYPE**:表示类、接口(包括注释类型)或枚举声明;
|
||||||
- **FIELD**:字段声明(包括枚举常量)
|
- **FIELD**:字段声明(包括枚举常量);
|
||||||
- **METHOD**:方法声明
|
- **METHOD**:方法声明;
|
||||||
- **PARAMETER**:参数声明
|
- **PARAMETER**:参数声明;
|
||||||
- **CONSTRUCTOR**:构造器声明
|
- **CONSTRUCTOR**:构造器声明;
|
||||||
- **LOCAL_VARIABLE**:本地变量声明
|
- **LOCAL_VARIABLE**:本地变量声明;
|
||||||
- **ANNOTATION_TYPE**:注解声明
|
- **ANNOTATION_TYPE**:注解声明;
|
||||||
- **PACKAGE**:包声明
|
- **PACKAGE**:包声明;
|
||||||
- **TYPE_PARAMETER**:类型参数声明
|
- **TYPE_PARAMETER**:类型参数声明;
|
||||||
- **TYPE_USE**:任何使用类型的语句
|
- **TYPE_USE**:任何使用类型的语句。
|
||||||
|
|
||||||
`@Retention`有以下可选值,其含义分别如下:
|
`@Retention` 有以下可选值,其含义分别如下:
|
||||||
|
|
||||||
- **SOURCE**:只在源代码中保留,编译器将代码编译为字节码后就会丢掉。
|
|
||||||
|
|
||||||
- **CLASS**:保留在字节码文件中,但虚拟机将 class 文件加载到内存时不一定会在内存中保留,这是默认的行为。
|
|
||||||
|
|
||||||
|
- **SOURCE**:只在源代码中保留,编译器将代码编译为字节码后就会丢掉;
|
||||||
|
- **CLASS**:保留在字节码文件中,但虚拟机将 class 文件加载到内存时不一定会在内存中保留,这是默认的行为;
|
||||||
- **RUNTIME**:一直保留到运行时,可以通过反射获取其信息。
|
- **RUNTIME**:一直保留到运行时,可以通过反射获取其信息。
|
||||||
|
|
||||||
### 2.2 注解信息
|
### 2.2 注解信息
|
||||||
|
|
||||||
对于`@Retention`类型为`RUNTIME`的注解,可以利用反射机制查看其信息。因为注解可以运用在不同目标上,所以 Class 、Field、Method、Constructor 都有如下方法:
|
对于 `@Retention` 类型为 `RUNTIME` 的注解,可以利用反射机制查看其信息。因为注解可以运用在不同目标上,所以 Class 、Field、Method、Constructor 都有如下方法:
|
||||||
|
|
||||||
```
|
```java
|
||||||
// 获取所有注解
|
// 获取所有注解
|
||||||
public Annotation[] getAnnotations()
|
public Annotation[] getAnnotations()
|
||||||
public Annotation[] getDeclaredAnnotations()
|
public Annotation[] getDeclaredAnnotations()
|
||||||
@ -291,13 +303,11 @@ public @interface Json {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class Test {
|
class Test {
|
||||||
|
|
||||||
static class Student {
|
static class Student {
|
||||||
/*当只有一个值并且其对应的方法名为value时候,可以省略 value = */
|
/*当只有一个值并且其对应的方法名为value时候,可以省略value = */
|
||||||
@Json("姓名")
|
@Json("姓名")
|
||||||
private String name;
|
private String name;
|
||||||
@Json(value = "出生日期", format = "yyyy-MM-dd HH:mm:ss")
|
@Json(value = "出生日期", format = "yyyy-MM-dd HH:mm:ss")
|
||||||
@ -337,7 +347,7 @@ class Test {
|
|||||||
|
|
||||||
### 2.3 注解继承
|
### 2.3 注解继承
|
||||||
|
|
||||||
一个常用的元注解是`@Inherited`,它表示某个注解是否能够被继承。示例如下:
|
一个常用的元注解是 `@Inherited`,它表示某个注解是否能够被继承。示例如下:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@ -348,7 +358,7 @@ public @interface ClassName {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
使用示例如下:此时如果加上`@Inherited`注解,则两者的输出都是 true;如果不加上`@Inherited`,第二行语句输出 false,代表子类 PrimaryStudent 没有继承到` @ClassName`注解。
|
使用示例如下,此时如果加上 `@Inherited` 注解,则两者的输出都是 true;如果不加上 `@Inherited` ,第二行语句输出 false,代表子类 PrimaryStudent 没有继承到 `@ClassName` 注解:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
class Test {
|
class Test {
|
||||||
@ -367,3 +377,6 @@ class Test {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 参考资料
|
||||||
|
|
||||||
|
+ 马俊昌 . Java编程的逻辑 . 机械工业出版社 . 2018-01-01
|
Loading…
x
Reference in New Issue
Block a user