反射是框架開發基石。本文演示如何獲取 Class 對象、掃描類的公共方法並解析簽名(返回類型、方法名、參數列表),附完整可運行代碼。
// 1. 類字面常量(編譯期已知類名)
Class<?> c1 = int.class; // 基本類型也有 Class 對象
Class<?> c2 = String.class;
Class<?> c3 = ReflectDemo.class;
// 2. 實例對象.getClass()(運行期已知對象)
ReflectDemo obj = new ReflectDemo();
Class<?> c4 = obj.getClass();
// 3. Class.forName("全限定名")(動態加載,常用於配置驅動)
Class<?> c5 = Class.forName("com.tsh.reflect.Foo");
驗證: 同一 JVM 中同一類只有一個 Class 實例,c1 == c2 為 true。
| 需求 | API | 返回類型 |
|---|---|---|
| 類全限定名 | clazz.getName() | String |
| 簡單類名 | clazz.getSimpleName() | String |
| 所有 public 方法(含繼承) | clazz.getMethods() | Method[] |
| 方法返回類型 | method.getReturnType() | Class |
| 方法名 | method.getName() | String |
| 參數類型列表 | method.getParameterTypes() | Class[] |
public static void printClass(Object obj) {
Class<?> c = obj.getClass();
System.out.println("類名:" + c.getName());
for (Method m : c.getMethods()) {
// 返回類型簡名
String ret = m.getReturnType().getSimpleName();
// 方法名
String name = m.getName();
// 參數列表簡名拼接
String params = Arrays.stream(m.getParameterTypes())
.map(Class::getSimpleName)
.collect(Collectors.joining(", "));
System.out.printf("%s %s(%s)%n", ret, name, params);
}
}
輸出範例:
類名:com.tsh.reflect.ReflectDemo
void main(String[])
void printClass(Object)
void wait(long, int)
void wait(long)
void wait()
boolean equals(Object)
...
注意:getMethods() 會遞歸包含父類(Object)的 public 方法;若只想要當前類聲明的方法,用 getDeclaredMethods()。
Class 對象是泛型(Class<T>),配合 clazz.newInstance() 可實例化對象(需無參構造且可訪問)。int.class)、void、陣列(String[].class)均有對應 Class 實例。