反射的定义以及基本使用
反射是 Java 语言中一个相当重要的特性,它允许正在运行的 Java 程序观测,甚至是修改程序的动态行为。表现为如下两点:
- 对于任意一个类,都能知道这个类的所有属性和方法
- 对于任意一个对象,都能调用它的任意一个属性和方法
反射涉及的 API 分为三类:Class、Member(Field、Method、Constructor)、Array and Enumerated。详细的基本使用可以参考我以前写的文章 反射基础使用,或者翻阅一下 官方文档。
这里只是简单的概括一下,已经熟悉的小伙伴可以跳过啦~~~
Class
获取 Class 的五种方式:
public final class Main {
enum E {
A, B
}
public static void main(String[] args) throws Exception {
// 1. Object.getClass()
Main main = new Main();
Class<?> clazzMain = main.getClass();
Class<?> clazzEnum = E.A.getClass();
String[] strings = new String[20];
Class<?> clazzStrings = strings.getClass();
// 2. The .class Syntax
Class<?> clazzMainSyntax = Main.class;
Class<?> clazzBoolean = boolean.class;
Class<?> clazzIntArray = int[][][].class;
// 3. Class.forName()
Class<?> clazzMainName = Class.forName("Main");
Class<?> clazzDoubleArray = Class.forName("[D");
Class<?> clazzStringArray = Class.forName("[[Ljava.lang.String;");
// 4. TYPE Field for Primitive Type Wrappers
Class<?> clazzDouble = Double.TYPE;
Class<?> clazzVoid = Void.TYPE;
// 5. Methods that Return Classes
Class<?> clazzSuperclass = Main.class.getSuperclass();
Class<?>[] clazzClasses = Main.class.getClasses();
Class<?>[] clazzDeclaredClasses = Main.class.getDeclaredClasses();
Class<?> clazzMainEnclose = Main.class.getEnclosingClass();
}
}
Member
Member 可能有的小伙伴没怎么见过,它只是一个接口,有三个我们最常见的三个实现类:
- Field
- Method
- Constructor
这里多说一点,这三个实现类都有一个相同的父类,AccessibleObject
,在访问私有属性时需要设置 setAccessible
关闭访问权限检查,就是出自这个类里面的方法。
由于篇幅限制,下面就只举例 Field 的使用,其他请参考官方文档:
public final class Main<T> {
private String s;
public static final int AGE = 18;
public float aFloat = 0f;
public boolean[][] booleans;
public List<String> list = new ArrayList<>();
public T t;
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("Main");
Object object = clazz.getConstructor().newInstance();
for (Field field : clazz.getDeclaredFields()) {
if (Modifier.isPrivate(field.getModifiers())) {
field.setAccessible(true);
}
System.out.println(field.getGenericType());
System.out.println(field.get(object));
System.out.println(Modifier.toString(field.getModifiers()));
System.out.println();
}
}
}
Arrays and Enumerated Types
这一小节讲的是两种特殊类型:数组和枚举。我是基本上从来没用过…
所以就简单的熟悉一下 API 好了。
Arrays
public final class Main<T> {
public String[] strings = new String[]{
"Demo", "Text"};
public static void main(String[] args) throws Exception {
Class<?> clazz = Main.class;
Object object = clazz.getConstructor().newInstance();
Field field = clazz.getField("strings");
if (field.getType().isArray()){
System.out.println(field.getName());
System.out.println(field.getGenericType());
String[] stringArray = (String[]) field.get(object);
for (String s : stringArray) {
System.out.println(s);
}
}
// 创建一维数组
Object array = Array