Java 反射篇(一)基础 API 总结
什么是反射?
反射机制是 Java 语言提供的一种基础功能,赋予程序在运行时自省(introspect,官方用语)的能力。通过反射我们可以直接操作类或者对象,比如获取某个对象的类定义,获取类声明的属性和方法,调用方法或者构造对象,甚至可以运行时修改类定义。
主要类:
1 | java.lang.Class |
工具类:
1 | java.lang.reflect.Modifier |
继承关系:
Class 类
如何获取一个 class
的 Class
实例?有几种方法:
1 | // 方法一:直接通过一个 class 的静态变量 class 获取 |
由于 Class
实例在 JVM 中是唯一的,因此,上述方法获取的 Class
实例都是同一个实例。可以用 ==
比较两个 Class
实例求证:
1 | // true |
拿到 Class
实例后,可以通过下列方法获取字段、方法、构造方法、注解,以进行后续操作。方法名以 getDeclared
开头的表示仅获取当前类的信息(不包括父类):
Member | Class API | Param type | Return type | Inherited members | Private members |
---|---|---|---|---|---|
Class |
getDeclaredClasses() |
Array | N | Y | |
getClasses() |
Array | Y | N | ||
Field |
getDeclaredField() |
String |
Single | N | Y |
getField() |
String |
Single | Y | java.lang.NoSuchFieldException |
|
getDeclaredFields() |
Array | N | Y | ||
getFields() |
Array | Y | N | ||
Method |
getDeclaredMethod() |
String , Class<?>... |
Single | N | Y |
getMethod() |
String , Class<?>... |
Single | Y | java.lang.NoSuchMethodException |
|
getDeclaredMethods() |
Array | N | Y | ||
getMethods() |
Array | Y | N | ||
Constructor |
getDeclaredConstructor() |
Class<?>... |
Single | N/A | Y |
getConstructor() |
Class<?>... |
Single | N/A | java.lang.NoSuchMethodException |
|
getDeclaredConstructors() |
Array | N/A | Y | ||
getConstructors() |
Array | N/A | N | ||
Annotation |
getDeclaredAnnotation() |
Class<T> |
Single | N | N/A |
getAnnotation() |
Class<T> |
Single | Y | N/A | |
getDeclaredAnnotationsByType() |
Class<T> |
Array | N | N/A | |
getAnnotationsByType() |
Class<T> |
Array | Y | N/A | |
getDeclaredAnnotations() |
Array | N | N/A | ||
getAnnotations() |
Array | Y | N/A |
字段
一个 Field
对象包含了一个字段的所有信息,例如:
1 | // 字段名称 |
以 String
类的 value
字段为例,它的定义是:
1 | public final class String { |
用反射获取该字段的信息,代码如下:
1 | Field f = String.class.getDeclaredField("value"); |
获取或设置字段值,使用如下方法。注意如果试图获取非 public
字段,将抛出异常 java.lang.IllegalAccessException
,解决办法是先设置 setAccessible(true)
:
1 | // 获取字段值 |
方法
一个 Method
对象包含一个方法的所有信息,例如:
1 | // 方法名称 |
方法调用:
1 | // 第一个参数为指定的实例对象。 |
构造方法
创建新实例的几种方式:
1 | // 方式一:通过 new 操作符 |
继承关系
通过以下方法获取父类或已实现接口:
1 | // 获取父类(Object 的父类是 null,其他任何非 interface 的 Class 都必定存在一个父类类型) |
isInstance
使用 instanceof
操作符或者 Class#isInstance
方法,可以判断一个实例的继承关系:
1 | Object n = Integer.valueOf(123); |
cast
如果 instanceof
为 true
,可以使用以下方法对实例进行强制类型转换:
1 | Number num1 = (Number) n; |
isAssignableFrom
如果是两个 Class
实例,要判断向上转型是否成立,可以调用 Class#isAssignableFrom
方法:
1 | Integer.class.isAssignableFrom(Integer.class); // true,因为Integer可以赋值给Integer |
参考
https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/index.html
https://docs.oracle.com/javase/tutorial/reflect/index.html
https://www.liaoxuefeng.com/wiki/1252599548343744/1255945147512512
API:
- https://docs.oracle.com/javase/8/docs/api/java/lang/Package.html
- https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html
- https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Field.html
- https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html
- https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Constructor.html
- https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Parameter.html