今日內容介紹
一、類加載器
二、反射構造方法
三、反射成員變量
四、反射成員方法
五、反射配置文件運行類中的方法java
當程序要使用某個類時,若是該類還未被加載到內存中,則系統會經過加載,鏈接,初始化三步來實現對這個類進行初始化。 * a 加載 * 就是指將class文件讀入內存,併爲之建立一個Class對象。 * 任何類被使用時系統都會創建一個Class對象 * b 鏈接 * 驗證 是否有正確的內部結構,並和其餘類協調一致 * 準備 負責爲類的靜態成員分配內存,並設置默認初始化值 * 解析 將類的二進制數據中的符號引用替換爲直接引用 * c 初始化 * 就是咱們之前講過的初始化步驟(new 對象) * 注:簡單的說就是:把.class文件加載到內存裏,並把這個.class文件封裝成一個Class類型的對象。
如下的狀況,會加載這個類。 * a. 建立類的實例 * b. 類的靜態變量,或者爲靜態變量賦值 * c. 類的靜態方法 * d. 使用反射方式來強制建立某個類或接口對應的java.lang.Class對象 * e. 初始化某個類的子類 * f. 直接使用java.exe命令來運行某個主類
負責將.class文件加載到內在中,併爲之生成對應的Class對象。 * a. Bootstrap ClassLoader 根類加載器 * 也被稱爲引導類加載器,負責Java核心類的加載 * 好比System,String等。在JDK中JRE的lib目錄下rt.jar文件中 * b. Extension ClassLoader 擴展類加載器 * 負責JRE的擴展目錄中jar包的加載。 * 在JDK中JRE的lib目錄下ext目錄 * c. System ClassLoader 系統類加載器 * 負責在JVM啓動時加載來自java命令的class文件,以及classpath環境變量所指定的jar包和類路徑。 * 咱們用的是System ClassLoader 系統類加載器
A. 反射定義數組
* a. JAVA反射機制是在運行狀態中, 對於任意一個類,都可以知道這個類的全部屬性和方法; 對於任意一個對象,都可以調用它的任意一個方法和屬性; 這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。 * b.反射技術 條件:運行狀態 已知:一個類或一個對象(根本是已知.class文件) 結果:獲得這個類或對象的全部方法和屬性 * 注: 要想解剖一個類,必須先要獲取到該類的字節碼文件對象。而解剖使用的就是Class類中的方法.因此先要獲取到每個字節碼文件對應的Class類型的對象。 *
B. Class類安全
* a. Class類及Class對象的瞭解 要想解剖一個類,必須先了解Class對象。 閱讀API的Class類得知,Class 沒有公共構造方法。Class 對象是在加載類時由 Java 虛擬機以及經過調用類加載器中的 defineClass 方法自動構造的。 * b. 獲得Class對象 * 1. 有三個方法 方式一: 經過Object類中的getClass()方法 Person person = new Person(); Class clazz = person.getClass(); 方式二: 經過 類名.class 獲取到字節碼文件對象(任意數據類型都具有一個class靜態屬性,看上去要比第一種方式簡單)。 Class clazz = Person.class; 方式三: 經過Class類中的方法(將類名做爲字符串傳遞給Class類中的靜態方法forName便可)。 Class c3 = Class.forName("Person"); 注:第三種和前兩種的區別是: 前兩種你必須明確Person類型. 後面是指定這種類型的字符串就行.這種擴展更強.我不須要知道你的類.我只提供字符串,按照配置文件加載就能夠了 * 2. 獲得Class對象的三個方法代碼演示: 代碼演示 /* * 獲取.class字節碼文件對象的方式 * 1:經過Object類中的getObject()方法 * 2: 經過 類名.class 獲取到字節碼文件對象 * 3: 反射中的方法, * public static Class<?> forName(String className) throws ClassNotFoundException * 返回與帶有給定字符串名的類或接口相關聯的 Class 對象 */ public class ReflectDemo { public static void main(String[] args) throws ClassNotFoundException { // 1: 經過Object類中的getObject()方法 // Person p1 = new Person(); // Class c1 = p1.getClass(); // System.out.println("c1 = "+ c1); // 2: 經過 類名.class 獲取到字節碼文件對象 // Class c2 = Person.class; // System.out.println("c2 = "+ c2); // 3: 反射中的方法 Class c3 = Class.forName("cn.itcast_01_Reflect.Person");// 包名.類名 System.out.println("c3 = " + c3); } } Person類 package cn.itcast_01_Reflect; public class Person { //成員變量 public String name; public int age; private String address; //構造方法 public Person() { System.out.println("空參數構造方法"); } public Person(String name) { this.name = name; System.out.println("帶有String的構造方法"); } //私有的構造方法 private Person(String name, int age){ this.name = name; this.age = age; System.out.println("帶有String,int的構造方法"); } public Person(String name, int age, String address){ this.name = name; this.age = age; this.address = address; System.out.println("帶有String, int, String的構造方法"); } //成員方法 //沒有返回值沒有參數的方法 public void method1(){ System.out.println("沒有返回值沒有參數的方法"); } //沒有返回值,有參數的方法 public void method2(String name){ System.out.println("沒有返回值,有參數的方法 name= "+ name); } //有返回值,沒有參數 public int method3(){ System.out.println("有返回值,沒有參數的方法"); return 123; } //有返回值,有參數的方法 public String method4(String name){ System.out.println("有返回值,有參數的方法"); return "哈哈" + name; } //私有方法 private void method5(){ System.out.println("私有方法"); } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", address=" + address+ "]"; } } * 注: Class類型的惟一性 由於一個.class文件在內存裏只生成一個Class對象,因此不管那一種方法獲得Class對象,獲得的都是同一個對象。
C.經過反射獲取無參構造方法並使用ide
* a. 獲得無參構造方法 public Constructor<?>[] getConstructors() 獲取全部的public 修飾的構造方法。 選擇無參構造方法,不建議使用。 public Constructor<T> getConstructor(Class<?>... parameterTypes) 獲取public修飾, 指定參數類型所對應的構造方法。 不傳參數獲得無參構造方法。 * b. 運行無參構造方法 public T newInstance(Object... initargs) 使用此 Constructor 對象表示的構造方法來建立該構造方法的聲明類的新實例,並用指定的初始化參數初始化該實例。 由於是無參構造,因此不傳參數。 * c. 經過反射獲取無參構造方法並使用的代碼演示: package cn.itcast.demo1; import java.lang.reflect.Constructor; /* * 經過反射獲取class文件中的構造方法,運行構造方法 * 運行構造方法,建立對象 * 獲取class文件對象 * 從class文件對象中,獲取須要的成員 * * Constructor 描述構造方法對象類 */ public class ReflectDemo1 { public static void main(String[] args) throws Exception { Class c = Class.forName("cn.itcast.demo1.Person"); //使用class文件對象,獲取類中的構造方法 // Constructor[] getConstructors() 獲取class文件對象中的全部公共的構造方法 /*Constructor[] cons = c.getConstructors(); for(Constructor con : cons){ System.out.println(con); }*/ //獲取指定的構造方法,空參數的構造方法 Constructor con = c.getConstructor(); //運行空參數構造方法,Constructor類方法 newInstance()運行獲取到的構造方法 Object obj = con.newInstance(); System.out.println(obj.toString()); } }
D. 經過反射獲取有參構造方法並使用函數
* a. 獲得有參的構造方法 public Constructor<T> getConstructor(Class<?>... parameterTypes) 獲取public修飾, 指定參數類型所對應的構造方法。 傳相應的參數類型獲得有參構造方法。 * b. 運行無參構造方法 public T newInstance(Object... initargs) 使用此 Constructor 對象表示的構造方法來建立該構造方法的聲明類的新實例,並用指定的初始化參數初始化該實例。 由於是有參構造,因此傳相應的參數值。 * c. 經過反射獲取有參構造方法並使用的代碼演示: package cn.itcast.demo1; import java.lang.reflect.Constructor; /* * 經過反射,獲取有參數的構造方法並運行 * 方法getConstructor,傳遞能夠構造方法相對應的參數列表便可 */ public class ReflectDemo2 { public static void main(String[] args)throws Exception { Class c = Class.forName("cn.itcast.demo1.Person"); //獲取帶有,String和int參數的構造方法 //Constructor<T> getConstructor(Class<?>... parameterTypes) //Class<?>... parameterTypes 傳遞要獲取的構造方法的參數列表 Constructor con = c.getConstructor(String.class,int.class); //運行構造方法 // T newInstance(Object... initargs) //Object... initargs 運行構造方法後,傳遞的實際參數 Object obj = con.newInstance("張三",20); System.out.println(obj); } }
F. 經過反射獲取私有構造方法並使用測試
* a. 獲得私有的構造方法 public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 獲取指定參數類型所對應的構造方法(包含私有的)。 public Constructor<?>[] getDeclaredConstructors() 獲取全部的構造方法(包含私有的)。 * b. 運行私有構造方法 public void setAccessible(boolean flag) 將此對象的 accessible 標誌設置爲指示的布爾值。 設置爲true,這個方法保證咱們獲得的私有構造方法的運行。(取消運行時期的權限檢查。) public T newInstance(Object... initargs) 使用此 Constructor 對象表示的構造方法來建立該構造方法的聲明類的新實例,並用指定的初始化參數初始化該實例。 * c. 經過反射獲取私有構造方法並使用的代碼演示: package cn.itcast.demo1; import java.lang.reflect.Constructor; /* * 反射獲取私有的構造方法運行 * 不推薦,破壞了程序的封裝性,安全性 * 暴力反射 */ public class ReflectDemo4 { public static void main(String[] args) throws Exception{ Class c = Class.forName("cn.itcast.demo1.Person"); //Constructor[] getDeclaredConstructors()獲取全部的構造方法,包括私有的 /*Constructor[] cons = c.getDeclaredConstructors(); for(Constructor con : cons){ System.out.println(con); }*/ //Constructor getDeclaredConstructor(Class...c)獲取到指定參數列表的構造方法 Constructor con = c.getDeclaredConstructor(int.class,String.class); //Constructor類,父類AccessibleObject,定義方法setAccessible(boolean b) con.setAccessible(true); Object obj = con.newInstance(18,"lisi"); System.out.println(obj); } } * 注:不推薦,破壞了程序的封裝性,安全性。 *
G. 反射獲取成員變量並改值this
* a. 獲取成員變量 * 獲得公共的成員變量 public Field getField(String name) 返回一個 Field 對象,它反映此 Class 對象所表示的類或接口的指定公共成員字段。 public Field[] getFields() 返回一個包含某些 Field 對象的數組,這些對象反映此 Class 對象所表示的類或接口的全部可訪問公共字段。 * 獲得全部的成員變量(包括私有的,若是要進行修改私有成員變量,要先進行public void setAccessible(boolean flag) 設置。) public Field getDeclaredField(String name) 返回一個 Field 對象,該對象反映此 Class 對象所表示的類或接口的指定已聲明字段。 public Field[] getDeclaredFields() 返回 Field 對象的一個數組,這些對象反映此 Class 對象所表示的類或接口所聲明的全部字段。 * b. 修改爲員變量(Field)的值 * 修改公共的成員變量 public void set(Object obj, Object value) 將指定對象變量上此 Field 對象表示的字段設置爲指定的新值。 obj指的是修改的是那個對象的這個成員變量值。 * c. 反射獲取成員變量並改值的代碼演示 package cn.itcast.demo1; import java.lang.reflect.Field; /* * 反射獲取成員變量,並修改值 * Person類中的成員String name */ public class ReflectDemo5 { public static void main(String[] args) throws Exception{ Class c = Class.forName("cn.itcast.demo1.Person"); Object obj = c.newInstance(); //獲取成員變量 Class類的方法 getFields() class文件中的全部公共的成員變量 //返回值是Field[] Field類描述成員變量對象的類 /*Field[] fields = c.getFields(); for(Field f : fields){ System.out.println(f); }*/ //獲取指定的成員變量 String name //Class類的方法 Field getField(傳遞字符串類型的變量名) 獲取指定的成員變量 Field field = c.getField("name"); //Field類的方法 void set(Object obj, Object value) ,修改爲員變量的值 //Object obj 必須有對象的支持, Object value 修改後的值 field.set(obj,"王五"); System.out.println(obj); } }
H. 反射獲取空參數成員方法並運行spa
* a. 獲取空參數成員方法 * 獲得公共的成員方法 public Method getMethod(String name, Class<?>... parameterTypes) 返回一個 Method 對象,它反映此 Class 對象所表示的類或接口的指定公共成員方法。 public Method[] getMethods() 返回一個包含某些 Method 對象的數組,這些對象反映此 Class對象所表示的類或接口(包括那些由該類或接口聲明的以及從超類和超接口繼承的那些的類或接口)的公共 member 方法。 * 獲得所有的成員方法(包括私有的,若是要使用私有成員方法,要先進行public void setAccessible(boolean flag) 設置。) public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回一個 Method 對象,該對象反映此 Class 對象所表示的類或接口的指定已聲明方法。 public Method[] getDeclaredMethods() 返回 Method 對象的一個數組,這些對象反映此 Class 對象表示的類或接口聲明的全部方法,包括公共、保護、默認(包)訪問和私有方法,但不包括繼承的方法。 * b. 使用Method方法對象 public Object invoke(Object obj, Object... args) 對帶有指定參數的指定對象調用由此 Method 對象表示的底層方法。 obj 指的是調這個方法的對象。 args 指的是調用這個方法所要用到的參數列表。 返回值Object就是方法的返回對象。若是方法沒有返回值 ,返回的是null. * c. 反射獲取空參數成員方法並運行代碼演示 package cn.itcast.demo1; import java.lang.reflect.Method; /* * 反射獲取成員方法並運行 * public void eat(){} */ public class ReflectDemo6 { public static void main(String[] args) throws Exception{ Class c = Class.forName("cn.itcast.demo1.Person"); Object obj = c.newInstance(); //獲取class對象中的成員方法 // Method[] getMethods()獲取的是class文件中的全部公共成員方法,包括繼承的 // Method類是描述成員方法的對象 /*Method[] methods = c.getMethods(); for(Method m : methods){ System.out.println(m); }*/ //獲取指定的方法eat運行 // Method getMethod(String methodName,Class...c) // methodName獲取的方法名 c 方法的參數列表 Method method = c.getMethod("eat"); //使用Method類中的方法,運行獲取到的方法eat //Object invoke(Object obj, Object...o) method.invoke(obj); } }
I. 反射獲取有參數成員方法並運行code
* a. 獲取有參數成員方法 * 獲得公共的成員方法 public Method getMethod(String name, Class<?>... parameterTypes) 返回一個 Method 對象,它反映此 Class 對象所表示的類或接口的指定公共成員方法。 public Method[] getMethods() 返回一個包含某些 Method 對象的數組,這些對象反映此 Class對象所表示的類或接口(包括那些由該類或接口聲明的以及從超類和超接口繼承的那些的類或接口)的公共 member 方法。 * 獲得所有的成員方法(包括私有的,若是要使用私有成員方法,要先進行public void setAccessible(boolean flag) 設置。) public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回一個 Method 對象,該對象反映此 Class 對象所表示的類或接口的指定已聲明方法。 public Method[] getDeclaredMethods() 返回 Method 對象的一個數組,這些對象反映此 Class 對象表示的類或接口聲明的全部方法,包括公共、保護、默認(包)訪問和私有方法,但不包括繼承的方法。 * b. 使用Method方法對象 public Object invoke(Object obj, Object... args) 對帶有指定參數的指定對象調用由此 Method 對象表示的底層方法。 obj 指的是調這個方法的對象。 args 指的是調用這個方法所要用到的參數列表。 返回值Object就是方法的返回對象。若是方法沒有返回值 ,返回的是null. * c. 反射獲取有參數成員方法並運行代碼演示 package cn.itcast.demo1; import java.lang.reflect.Method; /* * 反射獲取有參數的成員方法並執行 * public void sleep(String,int,double){} */ public class ReflectDemo7 { public static void main(String[] args) throws Exception{ Class c = Class.forName("cn.itcast.demo1.Person"); Object obj = c.newInstance(); //調用Class類的方法getMethod獲取指定的方法sleep Method method = c.getMethod("sleep", String.class,int.class,double.class); //調用Method類的方法invoke運行sleep方法 method.invoke(obj, "休眠",100,888.99); } }
J. 反射泛型擦除對象
* a. 使用狀況 例如:在泛型爲String的集合裏,添加Integer的數據 ArrayList<String> list = new ArrayList<String>(); list.add(100); * b. 能用泛型擦除的理論 僞泛型:在編譯後的.class文件裏面是沒有泛型的。類型爲Object。 用反射的方法繞過編譯,獲得Class文件對象,直接調用add方法。 * c. 反射泛型擦除的代碼演示 package cn.itcast.demo2; import java.lang.reflect.Method; import java.util.ArrayList; /* * 定義集合類,泛型String * 要求向集合中添加Integer類型 * * 反射方式,獲取出集合ArrayList類的class文件對象 * 經過class文件對象,調用add方法 * * 對反射調用方法是否理解 */ public class ReflectTest { public static void main(String[] args)throws Exception { ArrayList<String> array = new ArrayList<String>(); array.add("a"); //反射方式,獲取出集合ArrayList類的class文件對象 Class c = array.getClass(); //獲取ArrayList.class文件中的方法add Method method = c.getMethod("add",Object.class); //使用invoke運行ArrayList方法add method.invoke(array, 150); method.invoke(array, 1500); method.invoke(array, 15000); System.out.println(array); } }
K. 反射經過配置文件來決定運行的步驟
* a. 操做依據 經過配置文件獲得類名和要運行的方法名,用反射的操做類名獲得對象和調用方法 * b. 實現步驟: * 1. 準備配置文件,鍵值對 * 2. IO流讀取配置文件 Reader * 3. 文件中的鍵值對存儲到集合中 Properties * 集合保存的鍵值對,就是類名和方法名 * 4. 反射獲取指定類的class文件對象 * 5. class文件對象,獲取指定的方法 * 6. 運行方法 * c. 代碼演示 代碼: package cn.itcast.demo3; import java.io.FileReader; import java.lang.reflect.Method; import java.util.Properties; /* * 調用Person方法,調用Student方法,調用Worker方法 * 類不清楚,方法也不清楚 * 經過配置文件實現此功能 * 運行的類名和方法名字,以鍵值對的形式,寫在文本中 * 運行哪一個類,讀取配置文件便可 * 實現步驟: * 1. 準備配置文件,鍵值對 * 2. IO流讀取配置文件 Reader * 3. 文件中的鍵值對存儲到集合中 Properties * 集合保存的鍵值對,就是類名和方法名 * 4. 反射獲取指定類的class文件對象 * 5. class文件對象,獲取指定的方法 * 6. 運行方法 */ public class Test { public static void main(String[] args) throws Exception{ //IO流讀取配置文件 FileReader r = new FileReader("config.properties"); //建立集合對象 Properties pro = new Properties(); //調用集合方法load,傳遞流對象 pro.load(r); r.close(); //經過鍵獲取值 String className = pro.getProperty("className"); String methodName = pro.getProperty("methodName"); //反射獲取指定類的class文件對象 Class c = Class.forName(className); Object obj = c.newInstance(); //獲取指定的方法名 Method method = c.getMethod(methodName); method.invoke(obj); } } 配置文件: #className=cn.itcast.demo3.Student #methodName=study className=cn.itcast.demo3.Person methodName=eat #className=cn.itcast.demo3.Worker #methodName=job
做業測試
1.ArrayList
這個泛型爲Integer的ArrayList中存放一個String類型的對象
2.用反射去建立一個對象,有2種方式,儘可能用代碼去體現
4.編寫一個類A,增長一個實例方法showString,用於打印一條字符串,
在編寫一個類TestA ,做爲客戶端,用鍵盤輸入一個字符串,該字符串就是類A的全名,使用反射機制建立該類的對象, 並調用該對象中的方法showString
寫一個方法,此方法可將obj對象中名爲propertyName的屬性的值設置爲value.
public void setProperty(Object obj, String propertyName, Object value){ }
6.定義一個標準的JavaBean,名叫Person,包含屬性name、age。
使用反射的方式建立一個實例、調用構造函數初始化name、age,使用反射方式調用setName方法對名稱進行設置, 不使用setAge方法直接使用反射方式對age賦值。
7.已知一個類,定義以下:
package com.itheima; public class DemoClass { public void run() { System.out.println("welcome to heima!"); } } (1)寫一個Properties格式的配置文件,配置類的完整名稱。 (2) 寫一個程序,讀取這個Properties配置文件,得到類的完整名稱並加載這個類, (3)用反射 的方式運行run方法。
寫一個方法,此方法能夠獲取obj對象中名爲propertyName的屬性的值
public Object getProperty(Object obj, String propertyName, Object value){ }
答案:
1.ArrayList<Integer> list = new ArrayList<Integer>(); 這個泛型爲Integer的ArrayList中存放一個String類型的對象 package com.itheima.tests; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; /* * 1.ArrayList<Integer> list = new ArrayList<Integer>(); 爲這個泛型爲Integer的ArrayList中存放一個String類型的對象 */ public class Test01 { public static void main(String[] args) throws Exception { ArrayList<Integer> list = new ArrayList<Integer>(); list.add(10); System.out.println(list); //經過反射獲取ArrayList集合的字節碼對象 Class clazz = Class.forName("java.util.ArrayList"); //經過反射獲取add方法 Method addMethod = clazz.getMethod("add", Object.class); //經過反射調用addMethod方法 addMethod.invoke(list, "reflect is very good!"); System.out.println(list); // HashMap<Integer,Integer> hm = new HashMap<>(); } }
2.用反射去建立一個對象,有2種方式,儘可能用代碼去體現
package com.itheima.tests; import java.lang.reflect.Constructor; /** * 2.用反射去建立一個對象,有2種方式,儘可能用代碼去體現 * @author JX * */ public class Test02 { public static void main(String[] args) throws Exception { //獲取Student類的字節碼對象 Class clazz = Class.forName("com.itheima.tests.Student"); //1.利用反射建立一個空的對象 Student student = (Student)clazz.newInstance(); /*//2.獲取字段 Field ageField = clazz.getDeclaredField("age"); Field nameField = clazz.getDeclaredField("name"); //取出私有屬性 ageField.setAccessible(true); nameField.setAccessible(true); //3.給字段設置值 ageField.set(student, 30); nameField.set(student, "張三"); System.out.println(student);*/ /*Method setAgeMethod = clazz.getMethod("setAge", int.class); Method setNameMethod = clazz.getMethod("setName", String.class); setAgeMethod.invoke(student, 38); setNameMethod.invoke(student, "柳巖"); System.out.println(student);*/ //獲取有參構造 Constructor constructor = clazz.getConstructor(int.class,String.class); Student stu = (Student)constructor.newInstance(30,"張亮"); System.out.println(stu); } } class Student { private int age; private String name; public Student() { } public Student(int age, String name) { super(); this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student [age=" + age + ", name=" + name + "]"; } }
編寫一個類,增長一個實例方法用於打印一條字符串。
並使用反射手段建立該類的對象, 並調用該對象中的方法。
package com.itheima.tests; import java.lang.reflect.Method; /* * 3. 編寫一個類,增長一個實例方法用於打印一條字符串。 並使用反射手段建立該類的對象, 並調用該對象中的方法。 */ public class Test03 { public static void main(String[] args) throws Exception { //獲取Demo.java的字節碼對象 Class clazz = Class.forName("com.itheima.tests.Demo");//obj.getClass(); Student.class //利用反射建立對象 Demo demo = (Demo)clazz.newInstance(); //利用反射獲取print方法 Method printMethod = clazz.getMethod("print",String.class); printMethod.invoke(demo,"Android"); } } class Demo { public Demo() { } public void print(String str ){ System.out.println("Hello "+str); }
}
4.編寫一個類A,增長一個實例方法showString,用於打印一條字符串,
在編寫一個類TestA ,做爲客戶端,用鍵盤輸入一個字符串,該字符串就是類A的全名,使用反射機制建立該類的對象,並調用該對象中的方法showString
package com.itheima.tests; import java.lang.reflect.Method; import java.util.Scanner; /* * 4.編寫一個類A,增長一個實例方法showString,用於打印一條字符串, 在編寫一個類TestA ,做爲客戶端,用鍵盤輸入一個字符串,該字符串就是類A的全名,使用反射機制建立該類的對象, 並調用該對象中的方法showString */ public class Test04 { public static void main(String[] args) throws Exception{ Scanner sc = new Scanner(System.in); System.out.println("請輸入一個類的全類名,用.隔開:"); String className = sc.nextLine(); Class clazz = Class.forName(className);//obj.getClass(); Student.class //利用反射建立對象 A a = (A)clazz.newInstance(); //利用反射獲取print方法 Method printMethod = clazz.getMethod("showString"); printMethod.invoke(a); } } class A { public void showString() { System.out.println(" e m t f 明天必定經過!"); } }
寫一個方法,此方法可將obj對象中名爲propertyName的屬性的值設置爲value.
public void setProperty(Object obj, String propertyName, Object value){ } package com.itheima.tests; import java.lang.reflect.Field; /** * 5. 寫一個方法,此方法可將obj對象中名爲propertyName的屬性的值設置爲value. public void setProperty(Object obj, String propertyName, Object value){ } * @author JX * */ public class Test05 { public static void main(String[] args) throws Exception { Student student = new Student(30,"張三"); setProperty(student, "age", 25); System.out.println(student); Object obj = getProperty(student, "name"); System.out.println(obj); } //給對象obj的名字爲propertyName的屬性設置爲value public static void setProperty(Object obj, String propertyName, Object value) throws Exception{ //1.獲取obj的字節碼對象 Class clazz = obj.getClass(); //2.獲取propertyName屬性對應的Field對象 Field propertyNameField = clazz.getDeclaredField(propertyName); //3.設置成可訪問的 propertyNameField.setAccessible(true); //4.調用set方法給對象賦值 propertyNameField.set(obj, value); } //給對象obj的名字爲propertyName的屬性設置爲value public static Object getProperty(Object obj, String propertyName) throws Exception{ //1.獲取obj的字節碼對象 Class clazz = obj.getClass(); //2.獲取propertyName屬性對應的Field對象 Field propertyNameField = clazz.getDeclaredField(propertyName); //3.設置成可訪問的 propertyNameField.setAccessible(true); //4.調用get方法獲取該對象對應屬性的值 return propertyNameField.get(obj); } }
6.定義一個標準的JavaBean,名叫Person,包含屬性name、age。
使用反射的方式建立一個實例、調用構造函數初始化name、age,使用反射方式調用setName方法對名稱進行設置, 不使用setAge方法直接使用反射方式對age賦值。 package com.itheima.tests; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; /* * 6.定義一個標準的JavaBean,名叫Person,包含屬性name、age。 使用反射的方式建立一個實例、調用構造函數初始化name、age,使用反射方式調用setName方法對名稱進行設置, 不使用setAge方法直接使用反射方式對age賦值。 */ public class Test06 { public static void main(String[] args) throws Exception, SecurityException { //1.獲取Person類的字節碼對象 Class clazz = Person.class; //2.利用反射獲取有參構造方法 Constructor constructor = clazz.getConstructor(int.class,String.class); //3.調用構造方法,給屬性初始化 Person person = (Person)constructor.newInstance(30,"滅絕師太"); System.out.println(person); //4.使用反射方式調用setName方法對名稱進行設置 Method setNameMethod = clazz.getMethod("setName", String.class); setNameMethod.invoke(person, "張三丰"); //5.不使用setAge方法直接使用反射方式對age賦值。 Field ageField = clazz.getDeclaredField("age"); ageField.setAccessible(true); ageField.set(person, 50); System.out.println(person); } } class Person { private int age; private String name; public Person() { } public Person(int age, String name) { super(); this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person [age=" + age + ", name=" + name + "]"; } }
7.已知一個類,定義以下:
package com.itheima; public class DemoClass { public void run() { System.out.println("welcome to heima!"); } } (1)寫一個Properties格式的配置文件,配置類的完整名稱。 (2) 寫一個程序,讀取這個Properties配置文件,得到類的完整名稱並加載這個類, (3)用反射 的方式運行run方法。 package com.itheima.tests; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileReader; import java.lang.reflect.Method; import java.util.Properties; /** * 7.已知一個類,定義以下: package com.itheima.tests; public class DemoClass { public void run() { System.out.println("welcome to heima!"); } } (1)寫一個Properties格式的配置文件,配置類的完整名稱。 (2) 寫一個程序,讀取這個Properties配置文件,得到類的完整名稱並加載這個類, (3)用反射 的方式運行run方法。 * @author JX * */ public class Test07 { public static void main(String[] args) throws Exception { /*Properties props = new Properties(); props.load(new FileInputStream("src/config.properties")); String className = (String) props.get("className");*/ //定義字符緩衝輸入流 BufferedReader br = new BufferedReader(new FileReader("src/config.properties")); String line = br.readLine(); String className = line.split("=")[1]; // System.out.println(className); Class clazz = Class.forName(className); //利用反射建立一個對象 Object obj = clazz.newInstance(); //利用反射獲取run方法 Method runMethod = clazz.getMethod("run"); //利用反射調用run方法 runMethod.invoke(obj); } }
寫一個方法,此方法能夠獲取obj對象中名爲propertyName的屬性的值
public static Object getProperty(Object obj, String propertyName, Object value){ } package com.itheima.tests2; import java.lang.reflect.Field; public class Test08 { public static void main(String[] args) throws Exception { Person person = new Person(20,"張三"); String name = (String)getProperty(person, "name"); System.out.println(name); } public static Object getProperty(Object obj, String propertyName) throws Exception{ //獲取obj對象的字節碼文件對象 Class clazz = obj.getClass(); //獲取propertyName屬性所對應的字段 Field field = clazz.getDeclaredField(propertyName); //去掉私有屬性 field.setAccessible(true); return field.get(obj); } }