反射和方法/var 句柄是 Java 中的兩個強大功能,允許開發人員在運行時存取和操作物件。然而,它們存取和處理物件的方式有所不同。
讓我們來看一個如何使用反射來存取類別中方法的範例。我們將從一個名為「MyClass」的簡單類別開始,它有一個私有字串變數和該變數的 getter 方法。為了創建這個對象,我們可以使用普通的實例化:
MyClass objectInstance = new MyClass("John Doe");
要使用反射存取方法,我們需要先使用 getClass() 方法來取得物件實例的類別。然後,我們可以使用 getDeclaredMethod() 方法來尋找我們想要存取的方法,在本例中為「getName」。最後,我們需要使用 invoke() 方法呼叫該方法並傳入我們的物件實例。這是此過程的程式碼:
Class<?> clazz = objectInstance.getClass(); Method method = clazz.getDeclaredMethod("getName"); String value = (String) method.invoke(objectInstance); System.out.println(value); // prints "John Doe"
另一方面,MethodHandles 類別中的方法句柄提供了一種更安全、更優化的方法存取方法。這是因為它們是專門為此目的而設計的,並且針對 JVM 最佳化進行了增強。
使用方法句柄存取方法類似於使用反射。我們首先取得物件實例的類別。然後,我們使用 MethodHandles 上的 findVirtual() 方法來尋找我們想要存取的方法。接下來,我們使用 invoke() 方法呼叫該方法並傳入我們的物件實例。這是此過程的程式碼:
Class<?> clazz = objectInstance.getClass(); MethodHandle handle = MethodHandles.lookup().findVirtual(clazz, "getName", methodType(String.class)); String value = (String) handle.invoke(objectInstance); System.out.println(value); // Prints “John Doe”
但是,方法句柄的功能是有限的。它們無法處理諸如實例化類別之類的任務,而這可以透過反射來實現。
為了展示方法句柄的強大功能,讓我們來看看如何使用它們來直接存取類別中的私有欄位。假設我們的“MyClass”類別有一個名為“name”的私有字串變數。我們可以使用反射來存取它,但使用方法句柄是一種更安全的選擇。
要使用反射直接存取私有字段,我們首先需要取得物件實例的類別。然後,我們使用 getDeclaredField() 方法來尋找我們想要存取的字段,在本例中為「name」。但是,由於該欄位是私有的,因此我們需要使用 setAccessible() 方法將其可訪問性設為 true。最後,我們可以使用 get() 方法來檢索欄位的值。這是此過程的程式碼:
Class<?> clazz = objectInstance.getClass(); Field field = clazz.getDeclaredField("name"); field.setAccessible(true); String value = (String) field.get(objectInstance); System.out.println(value); // prints “John Doe”
使用方法句柄,過程類似。我們首先取得物件實例的類,然後使用 MethodHandles 上的 privateLookupIn() 方法來尊重欄位的存取修飾符(因為它是私有的)。接下來,我們使用 findVarHandle() 方法來尋找我們想要存取的欄位。最後,我們可以使用 get() 方法來檢索其值。這是此過程的程式碼:
Class<?> clazz = objectInstance.getClass(); VarHandle handle = MethodHandles.privateLookupIn(clazz, MethodHandles.lookup()).findVarHandle(clazz, "name", String.class); String value = (String) handle.get(objectInstance); System.out.println(value); // prints “John Doe”
出於效能原因,建議靜態實例化句柄,但這需要知道類別的名稱。如果您不知道類別的名稱,則無法使用此方法。
方法句柄的一個限制是它們不提供處理已檢查異常的方法。對方法句柄和 var 句柄的各種操作都會拋出已檢查的異常,必須在生產代碼中捕獲和聲明這些異常。
總之,方法和變數句柄在 JDK 中提供了一系列集中的功能,用於查找類元資料以及存取正常 Java 限制之外的方法和欄位。雖然它們沒有涵蓋反射的所有功能,但它們為這些任務提供了更安全、更優化的替代方案。
透過 MyExamCloud 的學習計畫體驗學習 Java 認證的最佳方式,並享受免費的練習測驗。
以上是在 Java 中使用方法和變數句柄進行運行時物件存取和操作的詳細內容。更多資訊請關注PHP中文網其他相關文章!