您好,登錄后才能下訂單哦!
這篇文章主要講解了“Java中的反射機制的基本運用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Java中的反射機制的基本運用”吧!
Java中的反射機制基本運用
1、什么是反射(reflect)
2、反射機制提供的功能
3、反射->獲取類對象
4、反射->利用無參構造實例化對象
5、反射->利用有參構造實例化對象
6、反射->調用無參方法
7、反射->調用有參方法
8、反射->訪問私有方法
9、反射->類加載路徑
看完反射可以了解一下注解
注解annotation://www.5655pk.com/article/221276.htm
反射是java的動態機制,它允許將對象的實例化,方案的調用,屬性的操作等從編碼期確定轉移到程序運行期確定。
反射能大大提高代碼的靈活度。但同時也帶來了更多的系統開銷和較慢的運行效率,因此程序不能過度依賴反射。
在運行時判斷任意一個對象所屬的類
在運行時構造任意一個類的對象(實例化)
在運行時判斷任意一個類所具有的成員變量和方法
在運行時調用任意一個對象的方法——動態代理
在開始之前創建一個實體類,用于測試反射機制
package reflect_text; /** * 用于測試反射機制 * * @author Akio * @Create 2021/8/14 10:37 */ public class Person { private String name = "劉瑜澄";//設置初始值 private int age = 22; public Person() {//無參構造 } public Person(String name, int age) {//有參構造 this.name = name; this.age = age; } public void sayHello() {//無參方法 System.out.println(name + ":使用sayHello方法"); } public void sayGoodBye() {//無參方法 System.out.println(name + ":使用sayGoodBye方法"); } public void say(String info) {//有參方法 System.out.println(name + ":" + info); } public void say(String info, int sum) {//有參方法(重載say方法) for (int i = 0; i < sum; i++) { System.out.println(name + ":" + info); } } private void privateMethod() {//私有方法 System.out.println(name + ":這是一個私有方法"); } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
以上這個用于測試反射的實體類創建成功后,先學習反射中是如何獲取類對象的。
反射的第一步就是要獲取操作類的類對象,即一個Class的實例,JVM中每個被加載的類有且只有一個類對象與之對應,獲取到這個類對象后我們就可以通過這個類對象來了解該類的一切信息(類名、有哪些方法、屬性等等) 以便在程序運行期間通過反射機制進行相關操作
這里介紹三種獲取類對象的方式:
(包名.)類名.class
Class personClass = reflect_text.Person.class; Class intClass = int.class;
這種方式最直接,但是由于是靠硬編碼形式寫死(編譯期間已經確定),因此不夠靈活。但是需要注意,基本類型(int\double等)只能通過這種方式獲取類對象
Class.forName(String className)
Class personClass = Class.forName("reflect_text.Person"); Class stringClass = Class.forName("java.lang.String");
這種方式較為常用,遵循運行期綁定。
類加載器ClassLoader
Class stringClass = ClassLoader.getSystemClassLoader().loadClass("java.lang.String"); Class personClass = ClassLoader.getSystemClassLoader().loadClass("reflect_text.Person");
在這一節中介紹幾個簡單的方法:
getName() 獲取類的完全限定名:包名.類名 getSimpleName() 僅僅獲取類名 getMethods() 返回一個Method數組,獲取class所表示的類的所有公開方法(包含從超類中繼承的方法)
例子:
Scanner scanner = new Scanner(System.in); Class cls = Class.forName(scanner.nextLine());//運行期綁定 String name = cls.getName();//獲取類的完全限定名:包名.類名 System.out.println("完全限定名 = " + name); name = cls.getSimpleName();//僅獲取類名 System.out.println("僅類名 = " + name); Method[] methods = cls.getMethods(); for (Method m : methods) { System.out.print(m.getName()+"\t"); }
Class類中提供了一個方法newInstance()來實例化,該方法要求此類必須具有無參構造器,它是通過無參構造器實例化對象的。
Person person = new Person(); //1獲取要實例化的類的類對象 Scanner scanner = new Scanner(System.in); System.out.println("請輸入類名:"); Class cls = Class.forName(scanner.nextLine()); /* 通過Class提供的方法newInstance()來實例化 該方法要求此類必須具有無參構造器,它是通過無參構造器實例化對象的 */ Object obj = cls.newInstance(); System.out.println("obj = " + obj);
getConstructor() //獲取無參構造器,可以利用無參構造器實例化對象,但這個方法對于使用無參構造器實例化對象可有可無 getConstructor(類對象) //通過類對象獲取特定的構造器,該參數列表是根據特定構造器的參數列表類型來決定的,如 getConstructor(String.class, int.class) 即為調用Person類中兩個參數的有參構造器 public Person(String name, int age) {//有參構造 this.name = name; this.age = age; }
舉例
//加載類對象 Class cls = Class.forName("reflect.Person"); //通過類對象獲取特定的構造器 Constructor c = cls.getConstructor(String.class, int.class); Object o = c.newInstance("流年", 21);//實例化 System.out.println(o);
結果可知初始值已經被修改
getMethod(String MethodName) 獲取類對象的MethodName方法,返回值類型為Method invoke(Object object) 執行object對象的某方法
舉例
//一般調用方法的做法------------------- Person p = new Person();//實例化對象 p.sayHello();//調用該對象方法 //反射機制調用方法----------------------- //1、實例化對象 Class cls = Class.forName("reflect_text.Person"); Object o = cls.newInstance(); //2、調用o的sayHello方案 //2.1通過Class獲取Person的sayHello方法 Method method = cls.getMethod("sayHello"); //2.2調用o的該方法 method.invoke(o);//等效于一般方法中的o.sayHello()
可見兩種操作均能達到一樣的效果
getMethod(String MethodName, 類對象) 獲取類對象的MethodName有參方法,并傳入對應參數類型的類對象,返回值類型為Method
舉例
//一般調用有參方法------------------------ Person p = new Person(); p.say("七夕快樂~"); p.say("七夕快樂~",3); //反射機制調用有參方法--------------------- Class cls = Class.forName("reflect_text.Person"); Object o = cls.newInstance(); //調用say(String info)方法 Method m1 = cls.getMethod("say", String.class); m1.invoke(o, "春節快樂~"); //調用say(String info, int sum) Method m2 = cls.getMethod("say", String.class, int.class); m2.invoke(o,"春節快樂~",3);
通過結果可以看到,效果都是一樣的
注意:反射訪問私有的方法,但是會破壞類的封裝性
getDeclaredMethod(String MethodName) 可以僅獲取此類定義的所有方法,包含私有方法 setAccessible(boolean flag) 開啟私有方法的訪問權限
舉例
//正常情況下,在本類中不可以訪問外部的私有方法 //但在反射機制中可行 Class cls = Class.forName("reflect_text.Person"); Object o = cls.newInstance(); Method method = cls.getDeclaredMethod("privateMethod"); method.setAccessible(true);//打開訪問權限 method.invoke(o);
加載資源時常用相對路徑,之前學習的相對路徑./由于運行環境不同,位置并非固定,因此實際開發中使用較少。
接下來介紹,在開發中常用的類加載路徑
常用的路徑通常為類的加載路徑,有兩個:
1:類對象.getResource()
與當前類所處同一目錄
2:類加載器.getResource()
類加載路徑,類的package定義中根包位置。
例如:有一個類: package reflect_text; public class WebServer{ …… } 在WebServer類中,當我們使用上述兩種方式獲取路徑時他們的對應位置為: WebServer.class.getResource() 當前WebServer所在的目錄(編譯后的class文件所在目錄) WebServer.class.getClassLoader().getResource() 則是在WebServer的包的最上級,即com包的上一級
package reflect_text; public class ReflectDemo { File dir = new File(ReflectDemo.class.getResource(".").toURI()); System.out.println("dir = " + dir); //dir = D:\ClassCode\JavaSE_API\out\production\JavaSE_API\reflect File dir2 = new File(ReflectDemo.class.getClassLoader().getResource(".").toURI()); System.out.println("dir2 = " + dir2); //dir2 = D:\ClassCode\JavaSE_API\out\production\JavaSE_API }
感謝各位的閱讀,以上就是“Java中的反射機制的基本運用”的內容了,經過本文的學習后,相信大家對Java中的反射機制的基本運用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。