java中的反射應(yīng)用實(shí)現(xiàn)
反射
我們先創(chuàng)建一個(gè)Student類出來(lái)。注意類中的成員變量、構(gòu)造方法、成員方法公共還是私有
package com.reflect; public class Student { //成員變量 public String name;//公共 private int age;//私有 //構(gòu)造方法 public Student() { super(); // TODO Auto-generated constructor stub } //私有構(gòu)造方法 private Student(String name) { this.name = name; } public Student(String name, int age) { super(); this.name = name; this.age = age; } //成員方法(getXxx/setXxx) public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } //成員方法 public void study() { System.out.println("我愛(ài)學(xué)習(xí)java!"); } // 私有 private void study(String string) { System.out.println("我還愛(ài)學(xué)習(xí)"+string); } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } }
反射概述
1、反射:反射是通過(guò)class文件對(duì)象,去使用文件對(duì)象的成員方法、構(gòu)造方法、成員變量
回想之前我們使用對(duì)象方法時(shí)必須通過(guò)new對(duì)象去使用。new Student().study(),此時(shí)我們就發(fā)現(xiàn)了一個(gè)問(wèn)題,小例中我們肯定是知道Student類中是有study()方法的,如果我們想使用用這個(gè)類但卻不清楚類中的信息,此時(shí)反射就起到了一定作用。
其實(shí)反射的作用,不止這一點(diǎn)點(diǎn)。如下
2、反射可以提高程序的靈活性和擴(kuò)展性,降低耦合性,提高自適應(yīng)能力。它允許程序創(chuàng)建和控制任何類的對(duì)象,無(wú)需提高硬編碼目標(biāo)類
Java反射技術(shù)應(yīng)用領(lǐng)域很廣,后期如軟件測(cè)試、JavaBean等都有很重要的作用
許多流行的開(kāi)源框架例如Struts、Hibernate、Spring在實(shí)現(xiàn)過(guò)程中都采用了該技術(shù)
3、性能問(wèn)題:使用反射基本上是一種解釋操作,用于字段和方法接入時(shí)要遠(yuǎn)慢于直接代碼。因此Java反射機(jī)制只要應(yīng)用在對(duì);靈活性和擴(kuò)展性要求很高的系統(tǒng)框架上,普通程序不建議使用使用反射會(huì)模糊程序內(nèi)部邏輯:程序員希望在代碼中看到程序的邏輯,反射等繞過(guò)了源代碼的技術(shù),因而會(huì)帶來(lái)維護(hù)問(wèn)題。
反射獲取Class類對(duì)象
- 要想使用反射,我們必須得到class文件對(duì)象,也就是我們要使用的類Class對(duì)象
- 三種獲得class文件對(duì)象的方法:
- Object類的getClass()方法
- 數(shù)據(jù)類型的靜態(tài)屬性class
- Class類中的靜態(tài)方法public static Class forName(String classname)
一般我們使用第三種
package com.reflect; public class Demo { public static void main(String[] args) throws ClassNotFoundException { // 方式1 Student p = new Student(); Class c = p.getClass(); Student p2 = new Student(); Class c2 = p2.getClass(); System.out.println(p == p2);// false不是同一Student對(duì)象 System.out.println(c == c2);// true是同一class對(duì)象 // 方式2 Class c3 = Student.class; System.out.println(c == c3);//true是同一class對(duì)象 // 方式3 // ClassNotFoundException(類找不到時(shí)) Class c4 = Class.forName("com.reflect.Student"); System.out.println(c == c4);//true是同一class對(duì)象 } }
Class類中相關(guān)的幾個(gè)類
- 和成員變量有關(guān) Field
- 和構(gòu)造方法有關(guān) Constructor
- 和成員方法有關(guān) Method
- 有關(guān)的幾個(gè)方法
- public T newInstance(Object… initargs) 使用此 Constructor 對(duì)象表示的構(gòu)造方法來(lái)創(chuàng)建該構(gòu)造方法的聲明類的新實(shí)例,并用指定的初始化參數(shù)初始化該實(shí)例。
反射獲取構(gòu)造方法
先來(lái)認(rèn)識(shí)幾個(gè)方法
public Constructor getConstructor()// 公共構(gòu)造方法對(duì)象 public Constructor[] getConstructors()//所有公共構(gòu)造方法對(duì)象 public Constructor[] getDeclaredConstructors()//所有構(gòu)造方法對(duì)象 public Constructor getDeclaredConstructor()//獲取私有構(gòu)造方法對(duì)象 public Constructor<T> getConstructor(Class<?>... parameterTypes)// 參數(shù)表示的是:你要獲取的構(gòu)造方法的構(gòu)造參數(shù)個(gè)數(shù)及數(shù)據(jù)類型的class字節(jié)碼文件對(duì)象 public void setAccessible(boolean flag)// 值為true則指示反射的對(duì)象在使用時(shí)應(yīng)該取消Java語(yǔ)言訪問(wèn)檢查。 暴力訪問(wèn)
package com.reflect; import java.lang.reflect.Constructor; public class ConstructorDemo { public static void main(String[] args) throws Exception { // 獲取字節(jié)碼文件對(duì)象 Class c = Class.forName("com.reflect.Student"); // 獲取所有構(gòu)造方法 Constructor[] cons = c.getDeclaredConstructors(); for (Constructor con : cons) { System.out.println(con); } // 獲取單個(gè)構(gòu)造方法 Constructor con = c.getConstructor();// 返回的是構(gòu)造方法對(duì)象 Constructor con1 = c.getConstructor(String.class, int.class);// 返回的是有參構(gòu)造方法對(duì)象 Constructor con2 = c.getDeclaredConstructor(String.class); //創(chuàng)建對(duì)象 Object obj = con.newInstance(); Object obj1=con1.newInstance("小米",12); // 暴力訪問(wèn) con2.setAccessible(true);// 值為true則指示反射的對(duì)象在使用時(shí)應(yīng)該取消Java語(yǔ)言訪問(wèn)檢查。 Object obj2 = con2.newInstance("小白"); System.out.println(obj.toString()); System.out.println(obj1.toString()); System.out.println(obj2.toString()); } }
運(yùn)行結(jié)果:
反射獲取成員變量
**類比上面Constructor類中的方法,這個(gè)類也有同樣的方法,獲取所有成員變量(返回?cái)?shù)組),獲取私有成員變量等 這里不再贅述 **
package com.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; /* * 通過(guò)發(fā)生獲取成員變量并使用 */ public class FieldDemo { public static void main(String[] args) throws Exception { // 獲取字節(jié)碼文件對(duì)象 Class c = Class.forName("com.reflect.Student"); // 獲取所有的成員變量 Field[] fields = c.getFields(); Field[] fields1 = c.getDeclaredFields(); for (Field field : fields1) { System.out.println(field); } /* * Person p = new Person(); p.address = "北京"; System.out.println(p); */ // 通過(guò)無(wú)參構(gòu)造方法創(chuàng)建對(duì)象 Constructor con = c.getConstructor(); Object obj = con.newInstance(); System.out.println(obj); // 獲取單個(gè)的成員變量 //通過(guò)成員變量名 Field nameField = c.getField("name"); // public void set(Object obj,Object value) // 將指定對(duì)象變量上此 Field 對(duì)象表示的字段設(shè)置為指定的新值。 nameField.set(obj, "小紅"); // 給obj對(duì)象的addressField字段設(shè)置值為"北京" System.out.println(obj); // 獲取age并對(duì)其賦值 // NoSuchFieldException 私有變量 Field ageField = c.getDeclaredField("age"); // IllegalAccessException 暴力訪問(wèn) ageField.setAccessible(true); ageField.set(obj, 18); System.out.println(obj); } }
運(yùn)行結(jié)果:
反射獲取成員方法
**類比上面Constructor類中的方法,這個(gè)類也有同樣的方法,獲取所有成員方法(返回?cái)?shù)組),獲取私有成員方法等 這里不再贅述 **
package com.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class MethodDemo { public static void main(String[] args) throws Exception { // 獲取字節(jié)碼文件對(duì)象 Class c = Class.forName("com.reflect.Student"); // 獲取所有的方法 Method[] methods = c.getMethods(); // 獲取自己的包括繼承父親的公共方法 Method[] methods1 = c.getDeclaredMethods(); // 獲取自己的所有的方法 for (Method method : methods1) { System.out.println(method); } Constructor con = c.getConstructor(); Object obj = con.newInstance(); // 獲取單個(gè)方法并使用 // public void show() // public Method getMethod(String name,Class<?>... parameterTypes) // 第一個(gè)參數(shù)表示的方法名,第二個(gè)參數(shù)表示的是方法的參數(shù)的class類型 Method m1 = c.getMethod("study"); // public Object invoke(Object obj,Object... args) // 返回值是Object接收,第一個(gè)參數(shù)表示對(duì)象是誰(shuí),第二參數(shù)表示調(diào)用該方法的實(shí)際參數(shù) m1.invoke(obj); // 調(diào)用obj對(duì)象的m1方法 System.out.println("----------"); Method m2 = c.getDeclaredMethod("study", String.class); // NoSuchMethodException 訪問(wèn)私有方法 暴力訪問(wèn) m2.setAccessible(true); m2.invoke(obj, "數(shù)學(xué)"); } }
運(yùn)行結(jié)果:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java 定時(shí)器(Timer)及線程池里使用定時(shí)器實(shí)例代碼
這篇文章主要介紹了Java 定時(shí)器(Timer)及線程池里使用定時(shí)器實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-12-12spring cloud gateway請(qǐng)求跨域問(wèn)題解決方案
這篇文章主要介紹了spring cloud gateway請(qǐng)求跨域問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01Java?詳細(xì)分析四個(gè)經(jīng)典鏈表面試題
兄弟們,編程,當(dāng)我們學(xué)習(xí)完數(shù)據(jù)結(jié)構(gòu)的時(shí)候,你就會(huì)有一種豁然開(kāi)朗的感覺(jué)。算是真正的入了編程的門,所以打好數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ)是特別特別重要的2022-03-03java實(shí)現(xiàn)文件上傳、下載、圖片預(yù)覽
這篇文章主要介紹了java實(shí)現(xiàn)文件上傳、下載、圖片預(yù)覽,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01java解析XML Node與Element的區(qū)別(推薦)
下面小編就為大家分享一篇java解析XML Node與Element的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01java8學(xué)習(xí)教程之函數(shù)引用的使用方法
這篇文章主要給大家介紹了關(guān)于java8學(xué)習(xí)教程之函數(shù)引用的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)下吧。2017-09-09Java設(shè)計(jì)模式以虹貓藍(lán)兔的故事講解橋接模式
橋接是用于把抽象化與實(shí)現(xiàn)化解耦,使二者可以獨(dú)立變化。這種類型的設(shè)計(jì)模式屬于結(jié)構(gòu)型模式,它通過(guò)提供抽象化和實(shí)現(xiàn)化之間的橋接結(jié)構(gòu),來(lái)實(shí)現(xiàn)二者的解耦。這種模式涉及到一個(gè)作為橋接的接口,使得實(shí)體類的功能獨(dú)立于接口實(shí)現(xiàn)類。這兩種類型的類可被結(jié)構(gòu)化改變而互不影響2022-04-04java面向?qū)ο笤O(shè)計(jì)原則之里氏替換原則示例詳解
這篇文章主要為大家介紹了java面向?qū)ο笤O(shè)計(jì)原則之里氏替換原則示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2021-10-10