首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 反射完全指南:從構造器、方法到字段的動態訪問實戰

     編輯:Java 綜合教學

前言

反射是 Java 動態性的核心,允許運行時檢查類結構、創建實例、調用方法、訪問字段,廣泛應用於框架開發(Spring、Hibernate、MyBatis 等)。本文以一個完整的 Person 類為例,系統演示反射的核心 API 用法。

示例類定義

package pro.shaowei.reflect;

public class Person {
    public String name;
    private int age;
    public Gender gender;
    private static String species = "人類";

    public Person() { this.name = "佚名"; this.age = -1; }
    public Person(String name) { this.name = name; }
    private Person(String name, int age) { this.name = name; this.age = age; }
    private Person(Gender g) { this.gender = g; }

    public void run() { System.out.println(name + " 跑!"); }
    public void attack() { System.out.println(name + " 打!"); }
    public void attack(String target) { System.out.println(name + " 打 " + target + "!"); }
    private void eat(String food) { System.out.println(name + " 吃 " + food); }
    public void introduce() { System.out.println("我叫" + name + ",今年" + age + "歲。"); }
    public static void playGame(String game) { System.out.println("玩 " + game + " 遊戲"); }

    public static void main(String[] args) { /* ... */ }
}

enum Gender { Male, Female }

核心反射操作分類

1. 構造器反射

類型關鍵 API代碼片段
公有無參clazz.getConstructor() / clazz.newInstance()Person p = (Person) clazz.newInstance();
公有有參clazz.getConstructor(String.class)Constructor c = clazz.getConstructor(String.class); p = (Person) c.newInstance("張三");
私有有參clazz.getDeclaredConstructor(...) + setAccessible(true)Constructor c = clazz.getDeclaredConstructor(String.class, int.class); c.setAccessible(true); p = (Person) c.newInstance("李四", 25);

2. 方法反射

類型獲取方式調用示例
公有無參getMethod("run")method.invoke(p);
公有有參getMethod("attack", String.class)method.invoke(p, "王五");
私有有參getDeclaredMethod("eat", String.class) + setAccessible(true)method.invoke(p, "香蕉");
靜態有參getDeclaredMethod("playGame", String.class)method.invoke(null, "掃雷"); // 靜態方法傳 null
main 方法getDeclaredMethod("main", String[].class)method.invoke(null, (Object) new String[]{"1","2"}); // 注意數組轉 Object

3. 字段反射

類型獲取方式讀寫示例
公有實例getField("name")field.get(p); field.set(p, "新名");
私有實例getDeclaredField("age") + setAccessible(true)field.get(p); field.set(p, 18);
私有靜態getDeclaredField("species") + setAccessible(true)field.get(null); field.set(null, "神族"); // 靜態字段傳 null

關鍵注意點總結

  1. getMethod vs getDeclaredMethod:前者只能獲取公有方法(含繼承),後者獲取本類聲明的所有方法(含私有),需配合 setAccessible(true) 破壞封裝。
  2. 靜態成員調用:invoke 第一個參數傳 null(或 Class 對象),而非實例。
  3. 數組參數傳遞:調用接受數組的方法(如 main)時,需將數組強轉為 Object,否則會被展開為可變參數。
  4. 性能考量:反射比直接調用慢,熱點代碼應緩存 Constructor/Method/Field 對象,或使用 MethodHandle/VarHandle(JDK 9+)。
  5. 安全性:setAccessible(true) 可能受 SecurityManager 限制,模塊化系統(JPMS)下需在 module-info.java 中 opens 相關包。

實戰應用場景

  • 框架通用對象映射(ORM、JSON 序列化)
  • 註解處理器、依賴注入容器
  • 動態代理、AOP 織入
  • 熱加載、插件系統
  • 測試框架訪問私有狀態

結語

反射打破了編譯時類型檢查的限制,賦予 Java 極大的靈活性。掌握其 API 體系與最佳實踐,是進階為框架開發者、源碼閱讀者的必經之路。建議結合 JDK 文檔與開源框架源碼(如 Spring 的 ReflectionUtils)深入鑽研。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved