程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 10分鐘帶你懂得Java中的反射

10分鐘帶你懂得Java中的反射

編輯:關於JAVA

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類的結構器對象,因為我們想要獲得的結構器的形參類型為Stringint,所以我們傳入String.classint.class。有了結構器對象,我們即可以挪用newInstance辦法來創立一個people對象。

留意,當經由過程反射獲得到類的 ConstructorMethodField對象後,在挪用這些對象的辦法之前,先將此對象的 accessible 標記設置為 true,以撤消 Java 說話拜訪檢討,可以晉升反射速度。如以下代碼所示:

Constructor<People> constructor = peopleClass.getConstructor(String.class, 
 int.class);
// 設置 constructor 的 Accessible屬性為ture以撤消Java的拜訪檢討
constructor.setAccessible(true);

經由過程反射獲得類中聲明的辦法

獲得以後類中聲明的辦法(不包含從父類繼續來的)

要獲得以後類中聲明的一切辦法可以經由過程 Class 中的 getDeclaredMethods 函數,它會獲得到以後類中聲明的一切辦法(包含privatepublicstatic等各類辦法),它會前往一個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()辦法的挪用。

獲得以後類中界說的屬性(不包含從父類繼續來的屬性)

要獲得以後類中界說的一切屬性(包含privatepublicstatic等各類屬性)可以挪用 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();
}

總結

以上就是這篇文章的全體內容,願望對年夜家的進修和任務能有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved