中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java反射機制詳解_動力節點Java學院整理

發布時間:2020-09-05 19:20:31 來源:腳本之家 閱讀:111 作者:mrr 欄目:編程語言

Java 反射機制介紹

Java 反射機制。通俗來講呢,就是在運行狀態中,我們可以根據“類的部分已經的信息”來還原“類的全部的信息”。這里“類的部分已經的信息”,可以是“類名”或“類的對象”等信息。“類的全部信息”就是指“類的屬性,方法,繼承關系和Annotation注解”等內容。

舉個簡單的例子:假設對于類ReflectionTest.java,我們知道的唯一信息是它的類名是“com.bjpowernode.Reflection”。這時,我們想要知道ReflectionTest.java的其它信息(比如它的構造函數,它的成員變量等等),要怎么辦呢?

這就需要用到“反射”。通過反射,我們可以解析出ReflectionTest.java的完整信息,包括它的構造函數,成員變量,繼承關系等等。

在了解了“java 反射機制”的概念之后,接下來思考一個問題:如何根據類的類名,來獲取類的完整信息呢?

這個過程主要分為兩步:

第1步:根據“類名”來獲取對應類的Class對象。

第2步:通過Class對象的函數接口,來讀取“類的構造函數,成員變量”等信息。

下面,我們根據示例來加深對這個概念的理解。示例如下(Demo1.java):

package com.bjpowernode.test;
import java.lang.Class;
public class Demo1 {
  public static void main(String[] args) {
    try {
      // 根據“類名”獲取 對應的Class對象
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 新建對象。newInstance()會調用類不帶參數的構造函數
      Object obj = cls.newInstance();
      System.out.println("cls="+cls);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
class Person {
  public Person() {
    System.out.println("create Person");
  }
}

運行結果:

create Person
cls=class com.bjpowernode.test.Person

說明:

(01) Person類的完整包名是"com.bjpowernode.test.Person"。而 Class.forName("com.bjpowernode.test.Person"); 這一句的作用是,就是根據Person的包名來獲取Person的Class對象。

(02) 接著,我們調用Class對象的newInstance()方法,創建Person對象。

現在,我們知道了“java反射機制”的概念以及它的原理。有了這個總體思想之后,接下來,我們可以開始對反射進行深入研究了。 

Class 詳細說明

1 獲取Class對象的方法

我這里總結了4種常用的“獲取Class對象”的方法:

方法1:Class.forName("類名字符串") (注意:類名字符串必須是全稱,包名+類名)

方法2:類名.class

方法3:實例對象.getClass()

方法4:"類名字符串".getClass()

下面,我們通過示例演示這4種方法。示例如下(Demo2.java):

package com.bjpowernode.test;
import java.lang.Class;
public class Demo2 {
  public static void main(String[] args) {
    try {
      // 方法1:Class.forName("類名字符串") (注意:類名字符串必須是全稱,包名+類名)
      //Class cls1 = Class.forName("com.bjpowernode.test.Person");
      Class<?> cls1 = Class.forName("com.bjpowernode.test.Person");
      //Class<Person> cls1 = Class.forName("com.bjpowernode.test.Person");
      // 方法2:類名.class
      Class cls2 = Person.class; 
      // 方法3:實例對象.getClass()
      Person person = new Person();
      Class cls3 = person.getClass();
      // 方法4:"類名字符串".getClass()
      String str = "com.bjpowernode.test.Person"; 
      Class cls4 = str.getClass();
      System.out.printf("cls1=%s, cls2=%s, cls3=%s, cls4=%s\n", cls1, cls2, cls3, cls4);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
class Person {
  public Person() {
    System.out.println("create Person");
  }
}

運行結果:

create Person
cls1=class com.bjpowernode.test.Person, cls2=class com.bjpowernode.test.Person, cls3=class com.bjpowernode.test.Person, cls4=class java.lang.String 

2 Class的API說明

Class的全部API如下表:

  Class的全部API如下表:

 public static Class  forName(String className)
 public static Class  forName(String name, boolean initialize, ClassLoader loader)
 public Constructor  getConstructor(Class[] parameterTypes)
 public Constructor[]  getConstructors()
 public Constructor  getDeclaredConstructor(Class[] parameterTypes)
 public Constructor[]  getDeclaredConstructors()
 public Constructor  getEnclosingConstructor()
 public Method  getMethod(String name, Class[] parameterTypes)
 public Method[]  getMethods()
 public Method  getDeclaredMethod(String name, Class[] parameterTypes)
 public Method[]  getDeclaredMethods()
 public Method  getEnclosingMethod()
 public Field  getField(String name)
 public Field[]  getFields()
 public Field  getDeclaredField(String name)
 public Field[]  getDeclaredFields()
 public Type[]  getGenericInterfaces()
 public Type  getGenericSuperclass()
 public Annotation<A>  getAnnotation(Class annotationClass)
 public Annotation[]  getAnnotations()
 public Annotation[]  getDeclaredAnnotations()
 public boolean  isAnnotation()
 public boolean  isAnnotationPresent(Class annotationClass)
 public boolean  isAnonymousClass()
 public boolean  isArray()
 public boolean  isAssignableFrom(Class cls)
 public boolean  desiredAssertionStatus()
 public Class<U>  asSubclass(Class clazz)
 public Class  getSuperclass()
 public Class  getComponentType()
 public Class  getDeclaringClass()
 public Class  getEnclosingClass()
 public Class[]  getClasses()
 public Class[]  getDeclaredClasses()
 public Class[]  getInterfaces()
 public boolean  isEnum()
 public boolean  isInstance(Object obj)
 public boolean  isInterface()
 public boolean  isLocalClass()
 public boolean  isMemberClass()
 public boolean  isPrimitive()
 public boolean  isSynthetic()
 public String  getSimpleName()
 public String  getName()
 public String  getCanonicalName()
 public String  toString()
 public ClassLoader  getClassLoader()
 public Package  getPackage()
 public int  getModifiers()
 public ProtectionDomain  getProtectionDomain()
 public URL  getResource(String name)
 public InputStream  getResourceAsStream(String name)
 public Object  cast(Object obj)
 public Object  newInstance()
 public Object[]  getSigners()
 public Object[]  getEnumConstants()
 public TypeVariable[]  getTypeParameters()

我們根據類的特性,將Class中的類分為4部分進行說明:構造函數,成員方法,成員變量,類的其它信息(如注解、包名、類名、繼承關系等等)。

2.1 構造函數

“構造函數”相關API

// 獲取“參數是parameterTypes”的public的構造函數
public Constructor  getConstructor(Class[] parameterTypes)
// 獲取全部的public的構造函數
public Constructor[]  getConstructors()
// 獲取“參數是parameterTypes”的,并且是類自身聲明的構造函數,包含public、protected和private方法。
public Constructor  getDeclaredConstructor(Class[] parameterTypes)
// 獲取類自身聲明的全部的構造函數,包含public、protected和private方法。
public Constructor[]  getDeclaredConstructors()
// 如果這個類是“其它類的構造函數中的內部類”,調用getEnclosingConstructor()就是這個類所在的構造函數;若不存在,返回null。
public Constructor  getEnclosingConstructor()

接下來,我們通過示例對這些API進行說明。示例代碼(DemoClassContructor.java)如下:

package com.bjpowernode.test;
import java.lang.Class;
import java.lang.reflect.Constructor;
/**
 * java Class類的Constructor相關API的測試函數
 *
 * 
 */
public class DemoClassContructor {
  public static void main(String[] args) {
    // getDeclaredConstructor() 的測試函數
    testGetDeclaredConstructor() ;
    // getConstructor() 的測試函數
    testGetConstructor() ;
    // getEnclosingConstructor() 的測試函數
    testGetEnclosingConstructor() ;
  }
  /**
   * getDeclaredConstructor() 的測試函數
   */
  public static void testGetDeclaredConstructor() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據class,獲取構造函數
      Constructor cst1 = cls.getDeclaredConstructor();
      Constructor cst2 = cls.getDeclaredConstructor(new Class[]{String.class});
      Constructor cst3 = cls.getDeclaredConstructor(new Class[]{String.class, int.class, Gender.class});
      // 根據構造函數,創建相應的對象
      cst1.setAccessible(true); // 因為Person中Person()是private的,所以這里要設置為可訪問
      Object p1 = cst1.newInstance();
      Object p2 = cst2.newInstance("Juce");
      Object p3 = cst3.newInstance("Jody", 34, Gender.MALE);
      System.out.printf("%-30s: p1=%s, p2=%s, p3=%s\n", 
          "getConstructor()", p1, p2, p3);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  /**
   * getConstructor() 的測試函數
   */
  public static void testGetConstructor() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據class,獲取構造函數
      //Constructor cst1 = cls.getConstructor(); // 拋出異常,因為默認構造函數是private權限。
      //Constructor cst2 = cls.getConstructor(new Class[]{String.class});// 拋出異常,因為該構造函數是protected權限。
      Constructor cst3 = cls.getConstructor(new Class[]{String.class, int.class, Gender.class});
      // 根據構造函數,創建相應的對象
      //Object p1 = cst1.newInstance();
      //cst1.setAccessible(true); // 因為Person中Person()是private的,所以這里要設置為可訪問
      //Object p1 = cst1.newInstance();
      //Object p2 = cst2.newInstance("Kim");
      Object p3 = cst3.newInstance("Katter", 36, Gender.MALE);
      System.out.printf("%-30s: p3=%s\n", 
          "getConstructor()", p3);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  /**
   * getEnclosingConstructor() 的測試函數
   */
  public static void testGetEnclosingConstructor() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據class,調用Person類中有內部類InnerA的構造函數
      Constructor cst = cls.getDeclaredConstructor(new Class[]{String.class, int.class});
      // 根據構造函數,創建相應的對象
      Object obj = cst.newInstance("Ammy", 18);
      System.out.printf("%-30s: obj=%s\n", 
          "getEnclosingConstructor()", obj);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
// 枚舉類型。表示“性別”
enum Gender{ 
  MALE, FEMALE
} 
// 人
class Person {
  private Gender gender; // 性別
  private int age;    // 年齡
  private String name;  // 姓名

  private Person() {
    this.name = "unknown";
    this.age = 0;
    this.gender = Gender.FEMALE;
    System.out.println("call--\"private Person()\"");
  }
  protected Person(String name) {
    this.name = name;
    this.age = 0;
    this.gender = Gender.FEMALE;
    System.out.println("call--\"protected Person(String name)\"");
  }
  public Person(String name, int age, Gender gender) {
    this.name = name;
    this.age = age;
    this.gender = gender;
    System.out.println("call--\"public Person(String name, int age, Gender gender)\"");
  }

  public Person(String name, int age) {
    this.name = name;
    this.age = age;
    this.gender = Gender.FEMALE;
    //內部類在構造方法中
    class InnerA{
    }
    // 獲取InnerA的Class對象
    Class cls = InnerA.class;

    // 獲取“封閉該內部類(InnerA)”的構造方法
    Constructor cst = cls.getEnclosingConstructor();
    
    System.out.println("call--\"public Person(String name, int age)\" cst="+cst);
  }
  @Override
  public String toString() {
    return "("+name+", "+age+", "+gender+")";
  }
}

注意:若程序無法運行,請檢查“forName()”中的包名是否正確!forName()的參數必須是,Person類的完整包名。
運行結果:

call--"private Person()"
call--"protected Person(String name)"
call--"public Person(String name, int age, Gender gender)"
getConstructor() : p1=(unknown, 0, FEMALE), p2=(Juce, 0, FEMALE), p3=(Jody, 34, MALE)
call--"public Person(String name, int age, Gender gender)"
getConstructor() : p3=(Katter, 36, MALE)
call--"public Person(String name, int age)" cst=public com.bjpowernode.test.Person(java.lang.String,int)
getEnclosingConstructor() : obj=(Ammy, 18, FEMALE)

說明:

(01) 首先,要搞清楚Person類,它是我們自定義的類。專門用來測試這些API的。Person中有一個成員變量gender;它是Gender對象,Gender是一個枚舉類。取值可以是MALE或者FEMALE。

(02) testGetDeclaredConstructor() 是“getDeclaredConstructor() 的測試函數”。getDeclaredConstructor()可以“獲取類中任意的構造函數,包含public、protected和private方法”。

(03) testGetConstructor() 是“getConstructor() 的測試函數”。getConstructor()只能“獲取類中public的構造函數”。

(04) testGetEnclosingConstructor() 是“getEnclosingConstructor() 的測試函數”。關于getEnclosingConstructor()的介紹,官方說法是“如果該 Class 對象表示構造方法中的一個本地或匿名類,則返回 Constructor 對象,它表示底層類的立即封閉構造方法。否則返回 null。” 通俗點來說,就是“如果一個類A的構造函數中定義了一個內部類InnerA,則通過InnerA的Class對象調用getEnclosingConstructor()方法,可以獲取類A的這個構造函數”。

2.2 成員方法

 “成員方法”相關API

// 獲取“名稱是name,參數是parameterTypes”的public的函數(包括從基類繼承的、從接口實現的所有public函數)
public Method  getMethod(String name, Class[] parameterTypes)
// 獲取全部的public的函數(包括從基類繼承的、從接口實現的所有public函數)
public Method[]  getMethods()
// 獲取“名稱是name,參數是parameterTypes”,并且是類自身聲明的函數,包含public、protected和private方法。
public Method  getDeclaredMethod(String name, Class[] parameterTypes)
// 獲取全部的類自身聲明的函數,包含public、protected和private方法。
public Method[]  getDeclaredMethods()
// 如果這個類是“其它類中某個方法的內部類”,調用getEnclosingMethod()就是這個類所在的方法;若不存在,返回null。
public Method  getEnclosingMethod()

接下來,我們通過示例對這些API進行說明。示例代碼(DemoClassMethod.java)如下:

package com.bjpowernode.test;
import java.lang.Class;
import java.lang.reflect.Method;
/**
 * java Class類的Method相關API的測試函數
 *
 * 
 */
public class DemoClassMethod {
  public static void main(String[] args) {
      // getDeclaredMethod() 的測試函數
      testGetDeclaredMethod() ;
      // getMethod() 的測試函數
      testGetMethod() ;
      // getEnclosingMethod() 的測試函數
      testGetEnclosingMethod() ;
  }
  /**
   * getDeclaredMethod() 的測試函數
   */
  public static void testGetDeclaredMethod() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據class,調用類的默認構造函數(不帶參數)
      Object person = cls.newInstance();
      // 獲取Person中的方法
      Method mSetName = cls.getDeclaredMethod("setName", new Class[]{String.class});
      Method mGetName = cls.getDeclaredMethod("getName", new Class[]{});
      Method mSetAge = cls.getDeclaredMethod("setAge", new Class[]{int.class});
      Method mGetAge = cls.getDeclaredMethod("getAge", new Class[]{});
      Method mSetGender = cls.getDeclaredMethod("setGender", new Class[]{Gender.class});
      Method mGetGender = cls.getDeclaredMethod("getGender", new Class[]{});
      // 調用獲取的方法
      mSetName.invoke(person, new Object[]{"Jimmy"});
      mSetAge.invoke(person, new Object[]{30});
      mSetGender.setAccessible(true);  // 因為Person中setGender()是private的,所以這里要設置為可訪問
      mSetGender.invoke(person, new Object[]{Gender.MALE});
      String name = (String)mGetName.invoke(person, new Object[]{});
      Integer age = (Integer)mGetAge.invoke(person, new Object[]{});
      mGetGender.setAccessible(true);  // 因為Person中getGender()是private的,所以這里要設置為可訪問
      Gender gender = (Gender)mGetGender.invoke(person, new Object[]{});
      // 打印輸出
      System.out.printf("%-30s: person=%s, name=%s, age=%s, gender=%s\n", 
          "getDeclaredMethod()", person, name, age, gender);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  /**
   * getMethod() 的測試函數
   */
  public static void testGetMethod() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據class,調用類的默認構造函數(不帶參數)
      Object person = cls.newInstance();
      // 獲取Person中的方法
      Method mSetName = cls.getMethod("setName", new Class[]{String.class});
      Method mGetName = cls.getMethod("getName", new Class[]{});
      //Method mSetAge = cls.getMethod("setAge", new Class[]{int.class});     // 拋出異常,因為setAge()是protected權限。
      //Method mGetAge = cls.getMethod("getAge", new Class[]{});         // 拋出異常,因為getAge()是protected權限。
      //Method mSetGender = cls.getMethod("setGender", new Class[]{Gender.class}); // 拋出異常,因為setGender()是private權限。
      //Method mGetGender = cls.getMethod("getGender", new Class[]{});       // 拋出異常,因為getGender()是private權限。
      // 調用獲取的方法
      mSetName.invoke(person, new Object[]{"Phobe"});
      //mSetAge.invoke(person, new Object[]{38});
      //mSetGender.invoke(person, new Object[]{Gender.FEMALE});
      String name = (String)mGetName.invoke(person, new Object[]{});
      //Integer age = (Integer)mGetAge.invoke(person, new Object[]{});
      //Gender gender = (Gender)mGetGender.invoke(person, new Object[]{});
      // 打印輸出
      System.out.printf("%-30s: person=%s\n", 
          "getMethod()", person);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  /**
   * getEnclosingMethod() 的測試函數
   */
  public static void testGetEnclosingMethod() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據class,調用類的默認構造函數(不帶參數)
      Object person = cls.newInstance();
      // 根據class,調用Person類中有內部類InnerB的函數
      Method mGetInner = cls.getDeclaredMethod("getInner", new Class[]{});
      // 根據構造函數,創建相應的對象
      mGetInner.invoke(person, new Object[]{});
      System.out.printf("%-30s: person=%s\n",
            "getEnclosingMethod", person);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
enum Gender{ 
  MALE, FEMALE
} 
class Person {
  private Gender gender; // 性別
  private int age;    // 年齡
  private String name;  // 姓名
  public Person() {
    this("unknown", 0, Gender.FEMALE);
  }
  public Person(String name, int age, Gender gender) {
    this.name = name;
    this.age = age;
    this.gender = gender;
  }
  // 獲取”姓名“。權限是 public
  public String getName() {
    return name;
  }
  // 設置”姓名“。權限是 public
  public void setName(String name) {
    this.name = name;
  }
  // 獲取”年齡“。權限是 protected
  protected int getAge() {
    return age;
  }
  // 設置”年齡“。權限是 protected
  protected void setAge(int age) {
    this.age = age;
  }
  // 獲取“性別”。權限是 private
  private Gender getGender() {
    return gender;
  }
  // 設置“性別”。權限是 private
  private void setGender(Gender gender) {
    this.gender = gender;
  }
  // getInner() 中有內部類InnerB,用來測試getEnclosingMethod()
  public void getInner() {
    // 內部類
    class InnerB{
    }
    // 獲取InnerB的Class對象
    Class cls = InnerB.class;
    // 獲取“封閉該內部類(InnerB)”的構造方法
    Method cst = cls.getEnclosingMethod();
    System.out.println("call--\"getInner()\" cst="+cst);
  }
  @Override
  public String toString() {
    return "("+name+", "+age+", "+gender+")";
  }
}

注意:若程序無法運行,請檢查“forName()”中的包名是否正確!forName()的參數必須是,Person類的完整包名。

運行結果:

getDeclaredMethod() : person=(Jimmy, 30, MALE), name=Jimmy, age=30, gender=MALE
getMethod() : person=(Phobe, 0, FEMALE)
call--"getInner()" cst=public void com.bjpowernode.test.Person.getInner()
getEnclosingMethod : person=(unknown, 0, FEMALE)

2.3 成員變量

“成員變量”的相關API

// 獲取“名稱是name”的public的成員變量(包括從基類繼承的、從接口實現的所有public成員變量)
public Field  getField(String name)
// 獲取全部的public成員變量(包括從基類繼承的、從接口實現的所有public成員變量)
public Field[]  getFields()
// 獲取“名稱是name”,并且是類自身聲明的成員變量,包含public、protected和private成員變量。
public Field  getDeclaredField(String name)
// 獲取全部的類自身聲明的成員變量,包含public、protected和private成員變量。
public Field[]  getDeclaredFields()
接下來,我們通過示例對這些API進行說明。示例代碼(DemoClassField.java)如下:
package com.bjpowernode.test;
import java.lang.Class;
import java.lang.reflect.Field;
/**
 * java Class類的"成員變量"相關API的測試函數
 *
 * 
 */
public class DemoClassField {
  public static void main(String[] args) {
    // getDeclaredField() 的測試函數
    testGetDeclaredField() ;
    // getField() 的測試函數
    testGetField() ;
  }
  /**
   * getDeclaredField() 的測試函數
   * getDeclaredField() 用于獲取的是類自身聲明的所有成員遍歷,包含public、protected和private方法。
   */
  public static void testGetDeclaredField() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據class,調用類的默認構造函數(不帶參數)
      Object person = cls.newInstance();
      // 根據class,獲取Filed
      Field fName = cls.getDeclaredField("name");
      Field fAge = cls.getDeclaredField("age");
      Field fGender = cls.getDeclaredField("gender");
      // 根據構造函數,創建相應的對象
      fName.set(person, "Hamier");
      fAge.set(person, 31);
      fGender.setAccessible(true); // 因為"flag"是private權限,所以要設置訪問權限為true;否則,會拋出異常。
      fGender.set(person, Gender.FEMALE);
      System.out.printf("%-30s: person=%s\n", 
          "getDeclaredField()", person);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  /**
   * getField() 的測試函數
   * getField() 用于獲取的是public的“成員”
   */
  public static void testGetField() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據class,調用類的默認構造函數(不帶參數)
      Object person = cls.newInstance();
      // 根據class,獲取Filed
      Field fName = cls.getField("name");
      Field fAge = cls.getDeclaredField("age");    // 拋出異常,因為Person中age是protected權限。 
      Field fGender = cls.getDeclaredField("gender"); // 拋出異常,因為Person中gender是private權限。 
      // 根據構造函數,創建相應的對象
      fName.set(person, "Grace");
      //fAge.set(person, 26);
      //fGender.set(person, Gender.FEMALE);
      System.out.printf("%-30s: person=%s\n", 
          "getField()", person);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
// 枚舉類型。表示“性別”
enum Gender{ 
  MALE, FEMALE
} 
// 人
class Person {
  // private。性別
  private Gender gender;
  // protected。 年齡
  protected int age;
  // public。 姓名
  public String name;
  public Person() {
    this("unknown", 0, Gender.FEMALE);
  }
  public Person(String name, int age, Gender gender) {
    this.name = name;
    this.age = age;
    this.gender = gender;
  }
  @Override
  public String toString() {
    return "("+name+", "+age+", "+gender+")";
  }
}

注意:若程序無法運行,請檢查“forName()”中的包名是否正確!forName()的參數必須是,Person類的完整包名。

運行結果:

getDeclaredField() : person=(Hamier, 31, FEMALE)
getField() : person=(Grace, 0, FEMALE)

2.4 類的其它信息

2.4.1 “注解”相關的API

// 獲取類的"annotationClass"類型的注解 (包括從基類繼承的、從接口實現的所有public成員變量)
public Annotation<A>  getAnnotation(Class annotationClass)
// 獲取類的全部注解 (包括從基類繼承的、從接口實現的所有public成員變量)
public Annotation[]  getAnnotations()
// 獲取類自身聲明的全部注解 (包含public、protected和private成員變量)
public Annotation[]  getDeclaredAnnotations()
接下來,我們通過示例對這些API進行說明。示例代碼(DemoClassAnnotation.java)如下:
package com.bjpowernode.test;
import java.lang.Class;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
 * java Class類getAnnotation()的測試程序
 */
public class DemoClassAnnotation {
  public static void main(String[] args) {
    try {
      // 根據“類名”獲取 對應的Class對象
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 獲取“Person類”的注解
      MyAnnotation myann = cls.getAnnotation(MyAnnotation.class);
      System.out.println("myann="+myann);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
/**
 * MyAnnotation是自定義個一個Annotation
 */
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
}
/**
 * MyAnnotation 是Person的注解。
 */
@MyAnnotation 
class Person {
}

注意:若程序無法運行,請檢查“forName()”中的包名是否正確!forName()的參數必須是,Person類的完整包名。

運行結果:

myann=@com.bjpowernode.test.MyAnnotation()

說明:

(01) MyAnnotation 是我們自定義個一個Annotation注解。若讀者不明白“注解”,可以參考博文“”TODO

(02) getAnnotation()就是獲取這個類的注解。

1.1.1.1

2.4.2 “父類”和“接口”相關的API

// 獲取實現的全部接口
public Type[]  getGenericInterfaces()
// 獲取父類
public Type  getGenericSuperclass()

示例代碼(DemoClassInterface.java)如下:

package com.bjpowernode.test;
import java.io.Serializable;
import java.lang.Runnable;
import java.lang.Thread;
import java.lang.Class;
import java.lang.reflect.Type;
/**
 * java Class類的有關父類和接口的測試
 */
public class DemoClassInterface {
  public static void main(String[] args) {
    try {
      // 根據“類名”獲取 對應的Class對象
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 獲取“Person”的父類
      Type father = cls.getGenericSuperclass();
      // 獲取“Person”實現的全部接口
      Type[] intfs = cls.getGenericInterfaces();
      System.out.println("father="+father);
      for (Type t:intfs)
        System.out.println("t="+t);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
/**
 * Person 繼承于 Object,并且實現了Serializable和Runnable接口
 */
class Person extends Object implements Serializable, Runnable{
  @Override
  public void run() {
  }
}

注意:若程序無法運行,請檢查“forName()”中的包名是否正確!forName()的參數必須是,Person類的完整包名。

運行結果:

father=class java.lang.Object
t=interface java.io.Serializable
t=interface java.lang.Runnable 

2.4.3 剩余的API

// 獲取“類名”
public String  getSimpleName()
// 獲取“完整類名”
public String  getName()
// 類是不是“枚舉類”
public boolean  isEnum()
// obj是不是類的對象
public boolean  isInstance(Object obj)
// 類是不是“接口”
public boolean  isInterface()
// 類是不是“本地類”。本地類,就是定義在方法內部的類。
public boolean  isLocalClass()
// 類是不是“成員類”。成員類,是內部類的一種,但是它不是“內部類”或“匿名類”。
public boolean  isMemberClass()
// 類是不是“基本類型”。 基本類型,包括void和boolean、byte、char、short、int、long、float 和 double這幾種類型。
public boolean  isPrimitive()
// 類是不是“復合類”。 JVM中才會產生復合類,在java應用程序中不存在“復合類”!
public boolean  isSynthetic()

示例代碼(DemoClassOtherAPIs.java)如下:

package com.bjpowernode.test;
import java.lang.Class;
import java.lang.Runnable;
import java.lang.annotation.ElementType;
import java.util.TreeMap;
/**
 * java Class類的getName(), isInterface()等測試程序
 *
 * 
 */
public class DemoClassOtherAPIs {
  public static void main(String[] args) {
    Class cls = DemoClassOtherAPIs.class;
    // 獲取“類名”
    System.out.printf("%-50s:getSimpleName()=%s\n", cls, cls.getSimpleName());
    // 獲取“完整類名”
    System.out.printf("%-50s:getName()=%s\n", cls, cls.getName());
    // 測試其它的API
    testOtherAPIs() ;
  }
  public static void testOtherAPIs() {
    // 本地類
    class LocalA {
    }
    // 測試枚舉類型。ElementType是一個枚舉類
    Class elementtypeCls = ElementType.class;
    System.out.printf("%-50s:isEnum()=%s\n", 
        elementtypeCls, elementtypeCls.isEnum());
    // 判斷是不是類的對象
    Class demoCls = DemoClassOtherAPIs.class;
    DemoClassOtherAPIs demoObj = new DemoClassOtherAPIs();
    System.out.printf("%-50s:isInstance(obj)=%s\n", 
        demoCls, demoCls.isInstance(demoObj));
    // 類是不是“接口”
    Class runCls = Runnable.class;
    System.out.printf("%-50s:isInterface()=%s\n", 
        runCls, runCls.isInterface());
    // 類是不是“本地類”。本地類,就是定義在方法內部的類。
    Class localCls = LocalA.class;
    System.out.printf("%-50s:isLocalClass()=%s\n", 
        localCls, localCls.isLocalClass());
    // 類是不是“成員類”。成員類,是內部類的一種,但是它不是“內部類”或“匿名類”。
    Class memCls = MemberB.class;
    System.out.printf("%-50s:isMemberClass()=%s\n", 
        memCls, memCls.isMemberClass());
    // 類是不是“基本類型”。 基本類型,包括void和boolean、byte、char、short、int、long、float 和 double這幾種類型。
    Class primCls = int.class;
    System.out.printf("%-50s:isPrimitive()=%s\n", 
        primCls, primCls.isPrimitive());
    // 類是不是“復合類”。 JVM中才會產生復合類,在java應用程序中不存在“復合類”!
    Class synCls = DemoClassOtherAPIs.class;
    System.out.printf("%-50s:isSynthetic()=%s\n", 
        synCls, synCls.isSynthetic());
  }
  // 內部成員類
  class MemberB {
  }
}

注意:若程序無法運行,請檢查“forName()”中的包名是否正確!forName()的參數必須是,Person類的完整包名。

運行結果:

class com.bjpowernode.test.DemoClassOtherAPIs :getSimpleName()=DemoClassOtherAPIs
class com.bjpowernode.test.DemoClassOtherAPIs :getName()=com.bjpowernode.test.DemoClassOtherAPIs
class java.lang.annotation.ElementType :isEnum()=true
class com.bjpowernode.test.DemoClassOtherAPIs :isInstance(obj)=true
interface java.lang.Runnable :isInterface()=true
class com.bjpowernode.test.DemoClassOtherAPIs$1LocalA :isLocalClass()=true
class com.bjpowernode.test.DemoClassOtherAPIs$MemberB :isMemberClass()=true
int :isPrimitive()=true
class com.bjpowernode.test.DemoClassOtherAPIs :isSynthetic()=false

說明:isSynthetic()是用來判斷Class是不是“復合類”。這在java應用程序中只會返回false,不會返回true。因為,JVM中才會產生復合類,在java應用程序中不存在“復合類”!

以上所述是小編給大家介紹的Java反射機制詳解_動力節點Java學院整理,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

高陵县| 丰宁| 大洼县| 平南县| 太仓市| 泰安市| 平阴县| 微博| 长沙县| 昌平区| 陆丰市| 阳高县| 阆中市| 晋州市| 金溪县| 油尖旺区| 京山县| 嘉禾县| 白银市| 涟水县| 天门市| 临高县| 略阳县| 太白县| 镇巴县| 枣阳市| 内黄县| 云梦县| 阿鲁科尔沁旗| 安顺市| 定陶县| 兴城市| 高平市| 高台县| 新邵县| 惠来县| 原平市| 高邑县| 大冶市| 错那县| 苍山县|