標籤:string 靜態 one wan 語言 from 運行 工作 des
Java反射的概念
Java反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態擷取的資訊以及動態調用對象的方法的功能稱為Java語言的反射機制
Java反射機制主要提供下面幾種用途:
1.在運行時判斷任意一個對象所屬的類
2.在運行時構造任意一個類的對象
3.在運行時判斷任意一個類所具有的成員變數和方法
4.在運行時調用任意一個對象的方法
首先看一個簡單的例子,通過這個例子來理解Java的反射機制是如何工作的
import java.lang.reflect.Method;/** * Java 反射練習。 * * @author Wanggc */public class ForNameTest { /** * 入口函數。 * * @param args * 參數 * @throws Exception * 錯誤資訊 */ public static void main(String[] args) throws Exception { // 獲得Class Class<?> cls = Class.forName(args[0]); // 通過Class獲得所對應對象的方法 Method[] methods = cls.getMethods(); // 輸出每個方法名 for (Method method : methods) { System.out.println(method); } }}程式碼範例如下
使用java的反射機制,一般需要遵循三步:
1.獲得你想操作類的Class對象
2.通過第一步獲得的Class對象去取得操作類的方法或是屬性名稱
3.操作第二步取得的方法或是屬性
Java啟動並執行時候,某個類無論產生多少個對象,他們都會對應同一個Class對象,它表示正在運行程式中的類和介面。如何取得操作類的Class對象,常用的有三種方式:
1.調用Class的靜態方法forName,如上例;
2.使用類的.class文法,如:Class<?> cls = String.class;
3.調用對象的getClass方法,如:String str = "abc";Class<?> cls = str .getClass();
下面將通過執行個體講述如何通過前面所訴的三步來執行某對象的某個方法:
3 import java.lang.reflect.Method; 4 5 /** 6 * Java 反射練習。 7 * 8 * @author Wanggc 9 */10 public class ReflectionTest {11 public static void main(String[] args) throws Exception {12 DisPlay disPlay = new DisPlay();13 // 獲得Class14 Class<?> cls = disPlay.getClass();15 // 通過Class獲得DisPlay類的show方法16 Method method = cls.getMethod("show", String.class);17 // 調用show方法18 method.invoke(disPlay, "Wanggc");19 }20 }21 22 class DisPlay {23 public void show(String name) {24 System.out.println("Hello :" + name);25 }26 }程式碼範例如下
上例講述了如何通過反射調用某個類的方法,下面將再通過一個執行個體講述如何通過反射給某個類的屬性賦值:
3 import java.lang.reflect.Field; 4 5 /** 6 * Java 反射之屬性練習。 7 * 8 * @author Wanggc 9 */ 10 public class ReflectionTest { 11 public static void main(String[] args) throws Exception { 12 // 建立學生對象 13 Student student = new Student(); 14 // 為學生對象賦值 15 student.setStuName("Wanggc"); 16 student.setStuAge(24); 17 // 建立拷貝目標對象 18 Student destStudent = new Student(); 19 // 拷貝學生對象 20 copyBean(student, destStudent); 21 // 輸出拷貝結果 22 System.out.println(destStudent.getStuName() + ":" 23 + destStudent.getStuAge()); 24 } 25 26 /** 27 * 拷貝學生對象資訊。 28 * 29 * @param from 30 * 拷貝來源物件 31 * @param dest 32 * 拷貝目標對象 33 * @throws Exception 34 * 例外 35 */ 36 private static void copyBean(Object from, Object dest) throws Exception { 37 // 取得拷貝來源物件的Class對象 38 Class<?> fromClass = from.getClass(); 39 // 取得拷貝來源物件的屬性列表 40 Field[] fromFields = fromClass.getDeclaredFields(); 41 // 取得拷貝目標對象的Class對象 42 Class<?> destClass = dest.getClass(); 43 Field destField = null; 44 for (Field fromField : fromFields) { 45 // 取得拷貝來源物件的屬性名稱字 46 String name = fromField.getName(); 47 // 取得拷貝目標對象的相同名稱的屬性 48 destField = destClass.getDeclaredField(name); 49 // 設定屬性的可訪問性 50 fromField.setAccessible(true); 51 destField.setAccessible(true); 52 // 將拷貝來源物件的屬性的值賦給拷貝目標對象相應的屬性 53 destField.set(dest, fromField.get(from)); 54 } 55 } 56 } 57 58 /** 59 * 學生類。 60 */ 61 class Student { 62 /** 姓名 */ 63 private String stuName; 64 /** 年齡 */ 65 private int stuAge; 66 67 /** 68 * 擷取學生姓名。 69 * 70 * @return 學生姓名 71 */ 72 public String getStuName() { 73 return stuName; 74 } 75 76 /** 77 * 設定學生姓名 78 * 79 * @param stuName 80 * 學生姓名 81 */ 82 public void setStuName(String stuName) { 83 this.stuName = stuName; 84 } 85 86 /** 87 * 擷取學生年齡 88 * 89 * @return 學生年齡 90 */ 91 public int getStuAge() { 92 return stuAge; 93 } 94 95 /** 96 * 設定學生年齡 97 * 98 * @param stuAge 99 * 學生年齡100 */101 public void setStuAge(int stuAge) {102 this.stuAge = stuAge;103 }104 }程式碼範例如下
前面講述了如何用Java反射機制操作一個類的方法和屬性,下面再通過一個執行個體講述如何在運行時建立類的一個對象:
3 import java.lang.reflect.Field; 4 5 /** 6 * Java 反射之屬性練習。 7 * 8 * @author Wanggc 9 */10 public class ReflectionTest {11 public static void main(String[] args) throws Exception {12 // 建立學生對象13 Student student = new Student();14 // 為學生對象賦值15 student.setStuName("Wanggc");16 student.setStuAge(24);17 // 建立拷貝目標對象18 Student destStudent = (Student) copyBean(student);19 // 輸出拷貝結果20 System.out.println(destStudent.getStuName() + ":"21 + destStudent.getStuAge());22 }23 24 /**25 * 拷貝學生對象資訊。26 * 27 * @param from28 * 拷貝來源物件29 * @param dest30 * 拷貝目標對象31 * @throws Exception32 * 例外33 */34 private static Object copyBean(Object from) throws Exception {35 // 取得拷貝來源物件的Class對象36 Class<?> fromClass = from.getClass();37 // 取得拷貝來源物件的屬性列表38 Field[] fromFields = fromClass.getDeclaredFields();39 // 取得拷貝目標對象的Class對象40 Object ints = fromClass.newInstance();41 for (Field fromField : fromFields) {42 // 設定屬性的可訪問性43 fromField.setAccessible(true);44 // 將拷貝來源物件的屬性的值賦給拷貝目標對象相應的屬性45 fromField.set(ints, fromField.get(from));46 }47 48 return ints;49 }50 }51 52 /**53 * 學生類。54 */55 class Student {56 /** 姓名 */57 private String stuName;58 /** 年齡 */59 private int stuAge;60 61 /**62 * 擷取學生姓名。63 * 64 * @return 學生姓名65 */66 public String getStuName() {67 return stuName;68 }69 70 /**71 * 設定學生姓名72 * 73 * @param stuName74 * 學生姓名75 */76 public void setStuName(String stuName) {77 this.stuName = stuName;78 }79 80 /**81 * 擷取學生年齡82 * 83 * @return 學生年齡84 */85 public int getStuAge() {86 return stuAge;87 }88 89 /**90 * 設定學生年齡91 * 92 * @param stuAge93 * 學生年齡94 */95 public void setStuAge(int stuAge) {96 this.stuAge = stuAge;97 }98 }程式碼範例如下
補充:在獲得類的方法、屬性、建構函式時,會有getXXX和getgetDeclaredXXX兩種對應的方法。之間的區別在於前者返回的是存取權限為public的方法和屬性,包括父類中的;但後者返回的是所有存取權限的方法和屬性,不包括父類的
Java中的反射機制