Java 反射程式設計(下)
文章目錄
- 反射與類操作(反射呼叫方法)
- 以上兩個方法返回的型別是 java.long.reflect.Method 類的物件. 在此類中提供有一個呼叫的方法支援,即如下 `最重要的方法:`
- 此類操作的好處是 : 不再侷限於某一具體型別的物件, 而是可以通過 Object 型別進行所有類的方法的呼叫
- 反射與類操作(反射呼叫成員)
- 在Class 類裡面提供了有兩組取得屬性操作的方法:
- java.lang.reflect.Field 類
- `在 AccessibleObject 中提供有一個方法 : 動態設定封裝, 也稱為 暴力反射`
- 但是如果在實際開發之中使用更多的屬性操作絕對不可能直接按照如上的模式進行, 一定要使用setter, getter 方法, 應該可以給使用者操作的機會. `在 Field 類中有一個特別有用的方法: 取得屬性型別`
- 將 Field 取得屬性與 Method 類中的 invoke() 結合一起, 可以編寫非常靈活的程式了.
反射與類操作(反射呼叫方法)
呼叫普通方法(核心)
在Class 類中定義有如下兩個取得類中普通方法的定義
- 取得全部方法
public Method[] getMethods()
throws SecurityException
- 取得指定的方法
(核心)
public Method getMethod(String name,
Class<?>... parameterTypes)
throws NoSuchMethodException,
SecurityException
以上兩個方法返回的型別是 java.long.reflect.Method 類的物件. 在此類中提供有一個呼叫的方法支援,即如下
最重要的方法:
public Object invoke(Object obj, Object... args)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
案例: 取得一個類中的全部方法
package com.beyond.dhl.exercise;
import java.lang.reflect.Method;
class Person{
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Test01 {
public static void main(String[] args) throws Exception {
Class<?> cls = Person.class;
Method met[] = cls.getMethods(); // 取得全部方法
for (int x = 0; x < met.length; x++) {
System.out.println(met[x]);
}
}
}
可以取得類中的全部方法, 包括繼承的Object類
那麼在之前所編寫的程式對於類中的 setter, getter 方法 採用的都是明確的物件呼叫. 而現在有了反射處理機制之後, 這個時候的程式即使你沒有明確的Person型別的物件(依然需要例項化物件, Object描述, 所有的普通方法必須在有例項化物件之後才可以進行呼叫), 就需要通過反射完成.
案例: 通過反射呼叫 setter和getter(有明確開發要求)
package com.beyond.dhl.exercise;
import java.lang.reflect.Method;
class Person{
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Test01 {
public static void main(String[] args) throws Exception {
String attribute = "name"; // 明確的告訴你屬性名稱
String value = "DHL"; // 明確告訴你要設定的內容
Class<?> cls = Class.forName("com.beyond.dhl.exercise.Person"); // Class.forName("com.beyond.dhl.exercise.Person") 相當於 Person.class
Object obj = cls.newInstance(); // 任何情況下呼叫類中的普通方法, 都必須有例項化物件
// 取得setName這個方法是例項化物件, 設定方法名稱和引數的型別
// setName() 是方法名稱, 但是這個方法名稱是根據給定的屬性的資訊拼湊得來的, 同時該方法需要接收一個String 型別的引數
Method setMethod = cls.getMethod("set"+initcap(attribute), String.class);
// 隨後需要通過Method類物件呼叫指定的方法, 呼叫方法必須有例項化物件, 同時要傳入一個引數
setMethod.invoke(obj, value); // 相當於: Person物件.setName(value)
Method getMethod = cls.getMethod("get"+initcap(attribute));
Object ret = getMethod.invoke(obj); // 相當於 Person物件.getName()
System.out.println(ret);
}
public static String initcap(String str) {
return str.substring(0,1).toUpperCase() + str.substring(1);
}
}
此類操作的好處是 : 不再侷限於某一具體型別的物件, 而是可以通過 Object 型別進行所有類的方法的呼叫
反射與類操作(反射呼叫成員)
在之前已經成功的實現了類的構造呼叫, 方法呼叫, 那麼除了這兩種模式之外還需要有成員呼叫.
前提: 類中的所有屬性一定要在類物件例項化之後才會進行空間的分配, 所有此時如果要想呼叫類的屬性, 必須要有例項化物件, 而通過反射的 newInstence() 方法可以直接取得例項化物件(Object 型別).
在Class 類裡面提供了有兩組取得屬性操作的方法:
1. 取得包括繼承類的屬性(是public許可權)(第一組)
1.1 取得類中的全部屬性
public Field[] getFields()
throws SecurityException
1.2 取得類中指定名稱的屬性
public Field getField(String name)
throws NoSuchFieldException,SecurityException
2. 取得本類屬性(第二組)(無許可權要求)
2.1 取得本類中的全部屬性
public Field[] getDeclaredFields()
throws SecurityException
2.2 取得本類中指定名稱的屬性
public Field getDeclaredField(String name)
throws NoSuchFieldException, SecurityException
案例: 取得類中的全部方法
package com.beyond.dhl.exercise;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
class Person{
private String name; // 此時的類中只是明確提供了一個屬性
protected String nickName; // 此時的類中只是明確提供了一個屬性
}
class Student extends Person{ // 做一個繼承關係
private String school;
public String nameString;
}
public class Test01 {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.beyond.dhl.exercise.Student");
{ // 普通程式碼塊
Field fields[] = cls.getFields(); // 取得全部屬性
for (int x = 0; x < fields.length; x++) {
System.out.println(fields[x]);
}
}
System.out.println("====================");
{ // 普通程式碼塊
Field fields[] = cls.getDeclaredFields(); // 取得全部屬性
for (int x = 0; x < fields.length; x++) {
System.out.println(fields[x]);
}
}
}
}
java.lang.reflect.Field 類
現在就需要關注屬性的核心描述類: java.lang.reflect.Field, 在這個類有兩個重要的方法:
1. 設定屬性內容(必須有了例項化物件才能開闢屬性的空間):
public void set(Object obj, Object value)
throws IllegalArgumentException, IllegalAccessException
2. 取得屬性內容:
public Object get(Object obj)
throws IllegalArgumentException, IllegalAccessException
在 AccessibleObject 中提供有一個方法 : 動態設定封裝, 也稱為 暴力反射
public void setAccessible(boolean flag)
throws SecurityException
即使用如下語句可以取消封裝:
nameField.setAccessible(true); // 取消封裝
案例: 通過反射操作類屬性
package com.beyond.dhl.exercise;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
class Person{
private String name; // 此時的類中只是明確提供了一個屬性
}
public class Test01 {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.beyond.dhl.exercise.Person");
Object obj = cls.newInstance(); // 例項化本類物件
Field nameField = cls.getDeclaredField("name");
nameField.setAccessible(true); // 取消封裝
nameField.set(obj, "張三"); // 等價於 物件.name = "張三";
System.out.println(nameField.get(obj)); // 取得屬性
}
}
注意:
但是如果在實際開發之中使用更多的屬性操作絕對不可能直接按照如上的模式進行, 一定要使用setter, getter 方法, 應該可以給使用者操作的機會.
在 Field 類中有一個特別有用的方法: 取得屬性型別
public Class<?> getType()
package com.beyond.dhl.exercise;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
class Person{
private String name; // 此時的類中只是明確提供了一個屬性
}
public class Test01 {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("com.beyond.dhl.exercise.Person");
Object obj = cls.newInstance(); // 例項化本類物件
Field nameField = cls.getDeclaredField("name");
System.out.println(nameField.getType().getName()); // 包.類
System.out.println(nameField.getType().getSimpleName()); // 類名
}
}
將 Field 取得屬性與 Method 類中的 invoke() 結合一起, 可以編寫非常靈活的程式了.
相關文章
- 重走JAVA程式設計之路(三)反射Java程式設計反射
- Java程式設計師都需要懂的「反射」Java程式設計師反射
- Java程式設計基礎28——反射&JDK新特性Java程式設計反射JDK
- Java程式設計師都要懂得知識點:反射Java程式設計師反射
- 好程式設計師Java培訓分享Java之反射技術程式設計師Java反射
- JAVA的基本程式設計結構(下)Java程式設計
- 14 Python物件導向程式設計:反射Python物件程式設計反射
- Java併發程式設計---java規範與模式下的併發程式設計1.1Java程式設計模式
- Java - 反射機制與工廠設計模式Java反射設計模式
- Java - 反射機制與單例設計模式Java反射單例設計模式
- 好程式設計師Java培訓分享註解與反射原理說明程式設計師Java反射
- JAVA併發程式設計實踐 下載Java程式設計
- JAVA_15 物件導向程式設計(下)Java物件程式設計
- 基於Java反射的定時任務設計Java反射
- Java程式設計:一步步教你如何深入瞭解神秘的Java反射機制Java程式設計反射
- 讀懂框架設計的靈魂—Java反射機制框架Java反射
- Java 網路程式設計(TCP程式設計 和 UDP程式設計)Java程式設計TCPUDP
- 好程式設計師Java培訓分享Java程式設計技巧程式設計師Java
- Java反射增強:程式碼模型Java反射模型
- JAVA網路程式設計(2)TCP程式設計Java程式設計TCP
- Java Socket程式設計Java程式設計
- Java程式設計:圖Java程式設計
- Java程式設計技巧Java程式設計
- 《JAVA語言程式設計》pdf 附下載連結Java程式設計
- java併發程式設計系列:牛逼的AQS(下)Java程式設計AQS
- 《Go 語言程式設計》讀書筆記(十)反射Go程式設計筆記反射
- Java ”框架 = 註解 + 反射 + 設計模式“ 之 註解詳解Java框架反射設計模式
- Java 網路程式設計 —— 非阻塞式程式設計Java程式設計
- Java程式設計師學習Rust程式設計 - infoworldJava程式設計師Rust
- 五種Java程式設計高效程式設計方法 - BablaJava程式設計
- java併發程式設計系列:java併發程式設計背景知識Java程式設計
- 【Java 反射學習】Java 反射基礎Java反射
- [Java 反射學習] Java 反射基礎Java反射
- 好程式設計師Java教程分享Java之設計模式程式設計師Java設計模式
- Java 程式設計開發Java程式設計
- java 併發程式設計Java程式設計
- java程式設計環境Java程式設計
- Java 網路程式設計Java程式設計