10分鐘帶你懂得Java中的反射。本站提示廣大學習愛好者:(10分鐘帶你懂得Java中的反射)文章只能為提供參考,不一定能成為您想要的結果。以下是10分鐘帶你懂得Java中的反射正文
1、簡介
Java 反射是可讓我們在運轉時獲得類的辦法、屬性、父類、接口等類的外部信息的機制。也就是說,反射實質上是一個“反著來”的進程。我們經由過程new
創立一個類的實例時,現實上是由Java虛擬機依據這個類的Class
對象在運轉時構建出來的,而反射是經由過程一個類的Class
對象來獲得它的界說信息,從而我們可以拜訪到它的屬性、辦法,曉得這個類的父類、完成了哪些接口等信息。
2、Class類
我們曉得應用javac可以或許將.java文件編譯為.class文件,這個.class文件包括了我們對類的原始界說信息(父類、接口、結構器、屬性、辦法等)。.class文件在運轉時會被ClassLoader
加載到Java虛擬機(JVM)中,當一個.class文件被加載後,JVM會為之生成一個Class對象,我們在法式中經由過程new實例化的對象現實上是在運轉時依據響應的Class對象結構出來的。確實的說,這個Class對象現實上是java.lang.Class<T>
泛型類的一個實例,好比Class<MyClass>
對象即為一個封裝了MyClass
類的界說信息的Class<T>
實例。因為java.lang.Class<T>
類不存在私有結構器,是以我們不克不及直接實例化這個類,我們可以經由過程以下辦法獲得一個Class對象。
鄙人面的講授中,我們將以People類和Student類為例:
public class People { private String name; private int age; public People(String name, int age) { this.name = name; this.age = age; } public int getAge() { return age; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public void setName(String name) { this.name = name; } public void speak() { System.out.println(getName() + " " + getAge()); } } public class Student extends People { private int grade; public Student(String name, int age) { super(name, age); } public Student(String name, int age, int grade) { super(name, age); this.grade = grade; } public int getGrade() { return grade; } public void setGrade(int grade) { this.grade = grade; } private void learn(String course) { System.out.println(name + " learn " + course); } }
經由過程類名獲得Class對象
若在編譯期曉得一個類的名字,我們可以如許獲得它的Class對象:
Class<People> peopleClass = People.class;
還有一種依據類的完全途徑名獲得Class對象的辦法以下所示:
//假定People類在com.test包中 Class<People> peopleClass = Class.forName("com.test.People");
留意,Class.forName()
辦法的參數必需是一個類的全途徑名。現實上,只需我們“import com.test.People",便可以直接經由過程”People.class
"獲得他的Class對象,而不消寫出全途徑這麼費事。 (若在挪用 Class.forName()
辦法時,沒有在classpath
找到對應的類,會拋出 ClassNotFoundException
。)
經由過程對象自己獲得其Class對象
People people = new People("Bill", 18); Class<People> peopleClass = people.getClass();
經由過程反射獲得類的結構器
一旦我們取得了People
的Class 對象,我們即可以經由過程這個Class 對象獲得到People
類的原始界說信息。 起首,我們來獲得People
類的結構器對象,有了這個結構器對象,我們便可以或許結構出一個People
對象出來。好比,我們可以在Student.java中添加以下代碼:
public static void main(String[] args) { Class<People> pClass = People.class; try { Constructor<People> constructor = pClass.getConstructor(String.class, int.class); People people = constructor.newInstance("Bill", 18); obj.speak(); } catch (Exception e) { } }
在下面,我們挪用getConstructor
辦法來獲得一個People
類的結構器對象,因為我們想要獲得的結構器的形參類型為String
和int
,所以我們傳入String.class
和int.class
。有了結構器對象,我們即可以挪用newInstance
辦法來創立一個people
對象。
留意,當經由過程反射獲得到類的 Constructor
、Method
、Field
對象後,在挪用這些對象的辦法之前,先將此對象的 accessible
標記設置為 true
,以撤消 Java 說話拜訪檢討,可以晉升反射速度。如以下代碼所示:
Constructor<People> constructor = peopleClass.getConstructor(String.class, int.class); // 設置 constructor 的 Accessible屬性為ture以撤消Java的拜訪檢討 constructor.setAccessible(true);
經由過程反射獲得類中聲明的辦法
獲得以後類中聲明的辦法(不包含從父類繼續來的)
要獲得以後類中聲明的一切辦法可以經由過程 Class 中的 getDeclaredMethods
函數,它會獲得到以後類中聲明的一切辦法(包含private
、public
、static
等各類辦法),它會前往一個Method
對象數組,個中的每一個Method
對象即表現了一個類中聲明的辦法。要想取得指定的辦法,可以挪用getDeclaredMethod(String name, Class...<T> parameterTypes)
。
如以下代碼所示 :
private static void showDeclaredMethods() { Student student = new Student("Bill", 18); //獲得Student類聲明的一切辦法 Method[] methods = student.getClass().getDeclaredMethods(); try { //獲得learnMethod對象(封裝了learn辦法) Method learnMethod = student.getClass().getDeclaredMethod("learn", String.class); //獲得learn辦法的參數列表並打印出來 Class<?>[] paramClasses = learnMethod.getParameterTypes() ; for (Class<?> class : paramClasses) { System.out.println("learn辦法的參數: " + class.getName()); } //斷定learn辦法能否為private System.out.println(learnMethod.getName() + " is private " + Modifier.isPrivate(learnMethod.getModifiers())); //挪用learn辦法 learnMethod.invoke(student, "Java Reflection"); } catch (Exception e) { } }
獲得以後類和父類中聲明的私有辦法
要獲得以後類和父類中聲明的一切 public
辦法可以挪用getMethods
函數,而要獲得某個指定的public
辦法,可以挪用getMethod
辦法。請看以下代碼:
private static void showMethods() { Student student = new Student("mr.simple"); // 獲得一切public辦法(包含Student自己的和從父類繼續來的) Method[] methods = student.getClass().getMethods(); try { //留意,經由過程 getMethod只能獲得public辦法,若測驗考試獲得private辦法則會拋出異常 Method learnMethod = student.getClass().getMethod("learn", String.class); } catch (Exception e) { } }
經由過程反射獲得類中界說的屬性
獲得屬性與獲得辦法是相似的,只不外把對getMethods()
/ getDeclaredMethods()
辦法的挪用換成了對getFields()
/ getDeclaredFields()
辦法的挪用。
獲得以後類中界說的屬性(不包含從父類繼續來的屬性)
要獲得以後類中界說的一切屬性(包含private
、public
、static
等各類屬性)可以挪用 Class對象的getDeclaredFields
函數;要想取得指定的屬性,可以挪用getDeclaredField
。
如以下代碼所示:
private static void showDeclaredFields() { Student student = new Student("Bill", 18); // 獲得以後類中界說的一切屬性 Field[] fields = student.getClass().getDeclaredFields(); try { // 獲得指定的屬性 Field gradeField = student.getClass().getDeclaredField("grade"); // 獲得屬性值 System.out.println("The grade is : " + gradeField.getInt(student)); // 設置屬性值 gradeField.set(student, 10); } catch (Exception e) { } }
獲得以後類和父類中界說的public屬性
要獲得以後類和父類中界說的一切public
屬性可以挪用Class
對象的getFields
函數,而要獲得某個指定的public
屬性,可以挪用getField
辦法,如以下代碼所示:
private static void showFields() { Student student = new Student("Bill", 18); // 獲得以後類和父類的一切public屬性 Field[] publicFields = student.getClass().getFields(); }
經由過程反射獲得類的父類及類所完成的接口
獲得父類
挪用Class
對象的getSuperClass
辦法便可,如以下代碼所示:
Student student = new Student("Bill", 18); Class<?> superClass = student.getClass().getSuperclass();
獲得所完成的接口
要曉得一個類完成了哪些接口,只需挪用Class
對象的getInterfaces
辦法,如以下代碼所示:
private static void showInterfaces() { Student student = new Student("Bill", 19); Class<?>[] interfaces = student.getClass().getInterfaces(); }
總結
以上就是這篇文章的全體內容,願望對年夜家的進修和任務能有所贊助。