1.反射基本概念:
?
01.定義:
反射是指在程序運行期間,能夠觀察和修改類或者類的對象的屬性和行為的特性!
?
?
02.作用:
001.在運行期間獲取類的修飾符,包名,類名,實現的接口,繼承的父類。
002.在運行期間獲取類的所有屬性名,修飾符,屬性類型。
003.在運行期間獲取所有方法,方法的返回值類型,方法名,方法參數數量,方法參數類型。
004.在運行期間加載類的方法。
?
?
03.java反射API常用的類
001.java.lang.Class
002.java.lang.reflect.Method
003.java.lang.Constructor
004.java.lang.Filed
005.java.lang.Modifier
2.例子
01.使用java反射獲取類的信息
001.父類代碼
package cn.pb.bean;/*** 父類* * @author Administrator* */ public class FatherTest {private String teststr = "測試用";public String getTeststr() {return teststr;}public void setTeststr(String teststr) {this.teststr = teststr;}}
002.子類代碼
package cn.pb.bean;/*** 測試類 人類 繼承了父類*/ import java.io.Serializable;public class Person extends FatherTest implements Serializable {private int id;private String name;private String address;private String message;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public Person() {super();}public Person(int id, String name, String address, String message) {super();this.id = id;this.name = name;this.address = address;this.message = message;}}
003.測試類代碼:
package cn.pb.test;/*** 測試類 通過反射獲取類的信息* * @author Administrator* */ public class GetClassInfo {public void test(String className) throws Exception {// 獲取Person類對象 傳遞的className為類的全類名Class clazz = Class.forName(className);// 獲取類在的包名 clazz.getSimpleName():獲取類名Package pkg = clazz.getPackage();System.out.println(clazz.getSimpleName() + "定義在" + pkg.getName()+ "包中!");System.out.println("*********************");// 獲取此對象所表示的實體(類,接口,基本類型或者void)的超類Class// 如果此對象是一個Object類,一個接口,一個基本類型或void,它的超類返回Null// 如果此對象是一個數組類,返回表示Object類的Class對象Class superClass = clazz.getSuperclass();System.out.println(clazz.getSimpleName() + "的超類是"+ superClass.getName());System.out.println("*********************");// 獲取Person類所實現的接口// 如果Person類沒有實現任何接口,返回一個長度為0的數組// 如果Person類是一個基本類型或者是void,那么也返回一個長度為0的數組Class[] interfaces = clazz.getInterfaces();System.out.println("所實現的接口有:");for (Class c : interfaces) {System.out.println(c.getName());}System.out.println("******************");}public static void main(String[] args) throws Exception {GetClassInfo getClassInfo = new GetClassInfo();getClassInfo.test("cn.pb.bean.Person");}}
02.使用java反射獲取類的構造函數的參數列表,并通過構造函數實例化類
001.父類代碼
package cn.pb.bean;/*** 父類* * @author Administrator* */ public class FatherTest {private String teststr = "測試用";public String getTeststr() {return teststr;}public void setTeststr(String teststr) {this.teststr = teststr;}}
?
002.子類代碼
package cn.pb.bean;/*** 測試類 人類 繼承了父類*/ import java.io.Serializable;public class Person extends FatherTest implements Serializable {private int id;private String name;private String address;private String message;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public Person() {super();System.out.println("通過無參構造實例化Person對象");}public Person(int id, String name, String address, String message) {super();this.id = id;this.name = name;this.address = address;this.message = message;System.out.println("通過有參構造實例化Person對象");}@Overridepublic String toString() {return "Person [id=" + id + ", name=" + name + ", address=" + address+ ", message=" + message + "]";}}
?
003.測試代碼
package cn.pb.test;import java.lang.reflect.Constructor;/*** 使用java反射獲取類的構造函數的參數列表,并通過構造函數實例化類* * @author Administrator* */ public class GetClassConstructorInfo {/*** 通過反射實例化類的對象* * @throws Exception*/public void test1() throws Exception {// 參數calssName,為類的全類名Class clazz = Class.forName("cn.pb.bean.Person");// 通過clazz.newInstance()方法,獲取類的實例Object obj = clazz.newInstance();System.out.println("通過反射實例化的對象:" + obj);}/*** 通過反射獲取類的構造函數* * @throws Exception*/public void test2() throws Exception {// 參數calssName,為類的全類名Class clazz = Class.forName("cn.pb.bean.Person");// 獲取類的構造函數,返回類的所有公共的構造函數Constructor[] constructors = clazz.getConstructors();System.out.println(clazz.getSimpleName() + "類的公共的構造函數以及構造函數的參數列表類型:");for (Constructor constructor : constructors) {System.out.println("構造函數的名稱為:" + constructor.getName());// 獲取構造函數的所有參數Class[] params = constructor.getParameterTypes();if (params.length == 0) {System.out.println("此構造函數沒有參數!");} else {System.out.println("該構造函數的參數列表為:【");for (int i = 0; i < params.length; i++) {if (i != 0) {System.out.println(",");}System.out.println(params[i].getName());}System.out.println("】");}}// 獲取無參構造,如果參數為空,則獲取無參構造Constructor constructor = clazz.getConstructor();// 通過無參構造方法獲取類的實例Object obj = constructor.newInstance();System.out.println("通過無參構造實例化的對象為:" + obj);/*** 獲取有參構造 這個方法只能獲得公共的有參構造 想要獲取私有的構造方法 可以使用* clazz.getDeclaredConstructor(int.class, String.class, String.class,* String.class);方法*/Constructor constructor2 = clazz.getConstructor(int.class,String.class, String.class, String.class);Object obj2 = constructor2.newInstance(12, "xiix", "hah", "wawa");System.out.println("通過有參構造實例化的 對象為:" + obj2);}public static void main(String[] args) throws Exception {GetClassConstructorInfo test = new GetClassConstructorInfo();// test.test1();test.test2();} }
?03.使用java反射獲取類的所有方法的信息,并調用類的setter方法進行屬性的賦值
?
001.父類代碼
package cn.pb.bean;/*** 父類* * @author Administrator* */ public class FatherTest {private String teststr = "測試用";public String getTeststr() {return teststr;}public void setTeststr(String teststr) {this.teststr = teststr;}}
?
002.子類代碼
package cn.pb.bean;/*** 測試類 人類 繼承了父類*/ import java.io.Serializable;public class Person extends FatherTest implements Serializable {private int id;private String name;private String address;private String message;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public Person() {super();System.out.println("通過無參構造實例化Person對象");}public Person(int id, String name, String address, String message) {super();this.id = id;this.name = name;this.address = address;this.message = message;System.out.println("通過有參構造實例化Person對象");}@Overridepublic String toString() {return "Person [id=" + id + ", name=" + name + ", address=" + address+ ", message=" + message + "]";}}
?
003.測試代碼
package cn.pb.test;/*** 使用java反射獲取類的所有方法的信息,并調用類的setter方法進行屬性的賦值*/ import java.lang.reflect.Method;public class GetClassMethodsInfo {/*** 調用類的setter方法進行屬性的賦值* * @param className* 類的全類名* @param propName* 屬性名* @param propType* 屬性類型* @param propValue* 屬性值* @throws Exception*/public void invokeSetter(String className, String propName,String propType, Object propValue) throws Exception {// 通過反射獲取類的實例Class clazz = Class.forName(className);Object obj = clazz.newInstance();// 將傳過來的屬性名 轉換成set方法String methodName = "set" + propName.substring(0, 1).toUpperCase()+ propName.substring(1);// 根據set方法名和參數列表獲取set方法Method method = clazz.getDeclaredMethod(methodName,Class.forName(propType));// 如果需要可以設置setAccessible方法,設置為可以訪問// method.setAccessible(true);// 調用方法并傳參 參數為:方法所屬的對象和方法的參數method.invoke(obj, propValue);//System.out.println("通過set方法給類的屬性賦值:" + obj);}/*** 使用java反射獲取類的所有方法的信息*/public void showMethods() throws Exception {Method[] methods;// 獲取Person類中的所有的方法,不包括繼承的類的方法// 如果該類或接口沒有生命任何方法,或者此Class 對象表示一個基本數據類型,一個數組類或void// 那么返回一個長度為0的數組methods = Class.forName("cn.pb.bean.Person").getDeclaredMethods();System.out.println("******展示方法信息********");for (Method method : methods) {System.out.println("方法名:" + method.getName());System.out.println("方法返回值類型:" + method.getReturnType().getName());// 獲取方法的參數列表Class[] params = method.getParameterTypes();if (params.length == 0) {System.out.println("該方法沒有參數!");} else {System.out.println("該方法的參數列表為:【");for (int i = 0; i < params.length; i++) {if (i != 0) {System.out.println(",");}System.out.println(params[i].getName());}System.out.println("】");}// 獲取方法所屬的類或接口的class對象Class declaringClass = method.getDeclaringClass();System.out.println("方法聲明在:" + declaringClass.getName() + "中!");// 獲取方法拋出的異常的類型,即throws子句中聲明的異常Class[] exceptions = method.getExceptionTypes();if (exceptions.length > 0) {System.out.println("該方法拋出的異常有:【");for (int i = 0; i < exceptions.length; i++) {if (i != 0) {System.out.println(",");}System.out.println(exceptions[i].getName());}System.out.println("】");}System.out.println("***********************");}}public static void main(String[] args) throws Exception {GetClassMethodsInfo test = new GetClassMethodsInfo();// test.invokeSetter("cn.pb.bean.Person", "name", "java.lang.String",// "zhangsan");test.showMethods();} }
?
?04.使用java反射獲取類的所有屬性的名稱和類型,并為其中一個屬性賦值
001.父類代碼
package cn.pb.bean;/*** 父類* * @author Administrator* */ public class FatherTest {private String teststr = "測試用";public String getTeststr() {return teststr;}public void setTeststr(String teststr) {this.teststr = teststr;}}
?
002.子類代碼
package cn.pb.bean;/*** 測試類 人類 繼承了父類*/ import java.io.Serializable;public class Person extends FatherTest implements Serializable {private int id;private String name;private String address;private String message;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public Person() {super();System.out.println("通過無參構造實例化Person對象");}public Person(int id, String name, String address, String message) {super();this.id = id;this.name = name;this.address = address;this.message = message;System.out.println("通過有參構造實例化Person對象");}@Overridepublic String toString() {return "Person [id=" + id + ", name=" + name + ", address=" + address+ ", message=" + message + "]";}}
?
003.測試代碼
package cn.pb.test;import java.lang.reflect.Field;/*** 使用java反射獲取類的所有屬性的名稱和類型,并為其中一個屬性賦值* * @author Administrator* */ public class GetClassFieldsInfo {/*** 使用java反射獲取類的所有屬性的名稱和類型* * @throws Exception*/public void showFields() throws Exception {Field[] fields;// 獲取Person類中的所有字段,但不包括繼承的字段// 如果該類或接口不聲明任何字段,或者此Class 對象表示一個基本數據類型,一個數組類或void// 那么返回一個長度為0的數組fields = Class.forName("cn.pb.bean.Person").getDeclaredFields();// 遍歷System.out.println("**********字段展示***********");for (Field field : fields) {System.out.println("字段名:" + field.getName());System.out.println("字段類型:" + field.getType().getName());System.out.println("********************");}}/*** 通過使用反射操作person類的字段 使用java反射獲取類的對象的實例,并為其中一個屬性賦值*/public void accessField() throws Exception {// 通過反射加載一個Person實例Class clazz = Class.forName("cn.pb.bean.Person");Object obj = clazz.newInstance();// 通過getDeclaredField("address")方法 獲取類的指定字段Field address = clazz.getDeclaredField("address");// address字段為private,這里已經超出其訪問范圍,不能直接訪問// 通過setAccessable方法,設定為可以訪問address.setAccessible(true);System.out.println("賦值前的address:" + address.get(obj));// 為address屬性賦值address.set(obj, "北大青鳥");System.out.println("賦值之后的address:" + address.get(obj));}public static void main(String[] args) throws Exception {GetClassFieldsInfo test = new GetClassFieldsInfo();test.showFields();test.accessField();}}