一、反射 1、反射概念 JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。 要想解剖一個類,必須先要獲取到該類的位元組碼文件對象。而解剖使用的就 ...
一、反射
1、反射概念
JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。
要想解剖一個類,必須先要獲取到該類的位元組碼文件對象。而解剖使用的就是Class類中的方法.所以先要獲取到每一個位元組碼文件對應的Class類型的對象。
2、Java 反射機制的主要用途
1、在運行時判斷任意一個對象所屬的類。
2、在運行時構造任意一個類的對象。
3、在運行時判斷任意一個類所具有的成員變數和方法。
4、在運行時調用任意一個對象的方法。
3、三種獲取Class實例對象的方式
1、Person p = new Person();
Class c = p.getClass();
已知類的對象,通過 getClass() 方法獲取 Class 實例對象。
2、Class c2 = Person.class;
任意數據類型都具備一個 class 靜態成員變數,看上去要比第一種方式簡單。
3、將類名作為字元串傳遞給Class類中的靜態方法 forName 即可。
Class c3 = Class.forName("Person");
1 import com.reflect.pojo.Product; 2 import org.junit.Test; 3 4 /** 5 * @author zt1994 2018/3/5 14:25 6 */ 7 public class TestReflect { 8 9 /** 10 * 測試三種獲取Class對象的方法 11 * @throws Exception 12 */ 13 @Test 14 public void testGetClass() throws Exception { 15 //實例化類的三種方法 任何對象都是Class的實例 16 //第一種 對象名.getClass() 17 Product product = new Product(); 18 Class<? extends Product> aClass1 = product.getClass(); 19 System.out.println(aClass1); //class com.reflect.pojo.Product 20 //第二種 類型.class 21 Class<Product> aClass2 = Product.class; 22 System.out.println(aClass2); 23 //第三種 Class 類中的靜態方法 static Class<?> forName(String className) className是類或者介面的許可權定名 24 Class<?> aClass3 = Class.forName("com.reflect.pojo.Product"); 25 System.out.println(aClass3); 26 //比較 27 System.out.println(aClass1==aClass2); //true 28 System.out.println(aClass1==aClass3); //true 29 System.out.println(aClass2==aClass3); //true 30 } 31 }
4、反射的作用
1、增加程式的靈活性,避免將程式寫死到代碼里(解除硬編碼的問題);
2、Java的反射機制它知道類的基本結構,可以動態的去獲取類這樣的結構的結構;
3、可以讓程式員在不知道其它程式員會有什麼類的時候就編寫完成自己的代碼;
4、反射的優點:靈活,功能強大(可以拿到私有的....);
5、反射的缺點:破壞封裝,影響性能;
5、反射運用(常用 API)
1、獲取構造方法
getConstructors 不能獲取私有的構造方法。
getDeclaredConstructors 可以獲取所有構造方法,包括私有的。
Product類:
1 public class Product { 2 private Integer id; 3 private String productName; 4 private Integer classifyId; 5 private String brand; 6 7 public Integer getId() { 8 return id; 9 } 10 11 public void setId(Integer id) { 12 this.id = id; 13 } 14 15 public String getProductName() { 16 return productName; 17 } 18 19 public void setProductName(String productName) { 20 this.productName = productName; 21 } 22 23 public Integer getClassifyId() { 24 return classifyId; 25 } 26 27 public void setClassifyId(Integer classifyId) { 28 this.classifyId = classifyId; 29 } 30 31 public String getBrand() { 32 return brand; 33 } 34 35 public void setBrand(String brand) { 36 this.brand = brand; 37 } 38 }
獲取構造方法:
1 /** 2 * 測試獲取構造方法 3 */ 4 @Test 5 public void testGetConstructor() throws ClassNotFoundException { 6 Class<?> aClass = Class.forName("com.reflect.pojo.Product"); 7 //獲取構造器 8 Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors(); 9 for (Constructor<?> declaredConstructor : declaredConstructors) { 10 System.out.println("declaredConstructor: [" + declaredConstructor + "]"); 11 } 12 }
2、反射創建對象
1、 newInstance()
註意 : 只能夠調用無參數的構造方法,無參數的構造方法必須是有許可權被訪問到的。
2、獲得構造器對象之後,通過構造器來創建對象
1 /** 2 * 測試反射創建對象的兩種方法 3 */ 4 @Test 5 public void testCreateInstance() throws Exception { 6 //方法一 Class類中有對應的方法 newInstance() 7 Class<?> aClass = Class.forName("com.reflect.pojo.Product"); 8 Product product = (Product) aClass.newInstance(); 9 10 //方法二 獲得構造器對象之後,通過構造器來創建對象 11 Constructor<?> constructor = aClass.getDeclaredConstructor(); 12 Product product1 = (Product) constructor.newInstance(); 13 }
3、獲取方法
1、獲取所有方法
getMethods
getDeclaredMethods
2、獲取單個方法
getMethod
getDeclaredMethod
1 /** 2 * 測試獲取方法 3 */ 4 @Test 5 public void testGetMethods() throws Exception{ 6 Class<?> aClass = Class.forName("com.reflect.pojo.Product"); 7 8 //獲取方法 9 Method[] declaredMethods = aClass.getDeclaredMethods(); 10 for (int i = 0; i < declaredMethods.length; i++){ 11 Method declaredMethod = declaredMethods[i]; 12 //獲取方法返回類型 13 Class<?> returnType = declaredMethod.getReturnType(); 14 //輸出方法返回類型 15 System.out.println("returnType: [" + returnType + "]"); 16 //獲取方法參數類型 17 Class<?>[] parameterTypes = declaredMethod.getParameterTypes(); 18 for (Class parameterType: parameterTypes){ 19 System.out.println("parameterType: [" + parameterType + "]"); 20 } 21 //輸出變數名稱 22 System.out.println("i: " + i + " declaredMethod: ["+declaredMethod.getName() + "]"); 23 } 24 }
4、獲取欄位(成員變數)
1、獲取所有欄位
getFields、getDeclaredFields
2、獲取單個欄位
getField、getDeclaredField
3、修改獲取欄位的值
set(Object obj,Object value); 將指定對象變數上此 Field 對象表示的欄位設置為指定的新值。
get(Object obj); 返回指定對象(傳入的obj)上此 Field 表示的欄位的值。
1 /** 2 * 獲取欄位 3 */ 4 @Test 5 public void testAPI() throws ClassNotFoundException { 6 //獲取field 7 Class<?> aClass = Class.forName("com.reflect.pojo.Product"); 8 //獲取欄位 9 Field[] declaredFields = aClass.getDeclaredFields(); 10 for (Field df:declaredFields){ 11 //獲取欄位類型 12 Class<?> type = df.getType(); 13 System.out.println("type: [" + type + "]"); 14 System.out.println(df); 15 } 16 }
5、通過反射調用方法
1、獲得類對應的Class實例;
2、通過反射得到類中的指定的方法
3、通過反射(Method類)來調用方法
Method中的方法:
Object invoke(Object obj, Object... args)
obj: 調用的對象
args: 方法參數
1 /** 2 * 反射調用方法 3 */ 4 @Test 5 public void testInvoke() throws Exception { 6 Product product = new Product(); 7 product.setId(7); 8 product.setClassifyId(3); 9 product.setBrand("聯想"); 10 product.setProductName("G480筆記本"); 11 12 //1.獲取位元組碼 13 Class<?> aClass = product.getClass(); 14 //2.獲取屬性 15 Field[] declaredFields = aClass.getDeclaredFields(); 16 //3.獲取屬性數組 17 for (Field declaredField : declaredFields) { 18 //獲取屬性名 19 String fieldName = declaredField.getName(); 20 //回去get方法字元串名 21 String methodName = "get" + toMethodName(fieldName); 22 //通過方法名稱使用反射獲取方法對象 23 Method method = aClass.getMethod(methodName); 24 //執行方法 25 Object invoke = method.invoke(product); 26 //裝換字元串類型 27 String s = String.valueOf(invoke); 28 System.out.println(fieldName + "=" + s); 29 } 30 }