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();
}
總結
以上就是這篇文章的全體內容,願望對年夜家的進修和任務能有所贊助。