欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java反射機制詳解_動力節(jié)點Java學(xué)院整理

 更新時間:2017年06月02日 14:26:57   投稿:mrr  
Java 反射機制。通俗來講呢,就是在運行狀態(tài)中,我們可以根據(jù)“類的部分已經(jīng)的信息”來還原“類的全部的信息”。這篇文章給大家詳細(xì)介紹了java反射機制的知識,感興趣的朋友一起看看吧

Java 反射機制介紹

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

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

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

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

這個過程主要分為兩步:

第1步:根據(jù)“類名”來獲取對應(yīng)類的Class對象。

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

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

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

運行結(jié)果:

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

說明:

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

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

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

Class 詳細(xì)說明

1 獲取Class對象的方法

我這里總結(jié)了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");
  }
}

運行結(jié)果:

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()

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

2.1 構(gòu)造函數(shù)

“構(gòu)造函數(shù)”相關(guān)API

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

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

package com.bjpowernode.test;
import java.lang.Class;
import java.lang.reflect.Constructor;
/**
 * java Class類的Constructor相關(guān)API的測試函數(shù)
 *
 * 
 */
public class DemoClassContructor {
  public static void main(String[] args) {
    // getDeclaredConstructor() 的測試函數(shù)
    testGetDeclaredConstructor() ;
    // getConstructor() 的測試函數(shù)
    testGetConstructor() ;
    // getEnclosingConstructor() 的測試函數(shù)
    testGetEnclosingConstructor() ;
  }
  /**
   * getDeclaredConstructor() 的測試函數(shù)
   */
  public static void testGetDeclaredConstructor() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據(jù)class,獲取構(gòu)造函數(shù)
      Constructor cst1 = cls.getDeclaredConstructor();
      Constructor cst2 = cls.getDeclaredConstructor(new Class[]{String.class});
      Constructor cst3 = cls.getDeclaredConstructor(new Class[]{String.class, int.class, Gender.class});
      // 根據(jù)構(gòu)造函數(shù),創(chuàng)建相應(yīng)的對象
      cst1.setAccessible(true); // 因為Person中Person()是private的,所以這里要設(shè)置為可訪問
      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() 的測試函數(shù)
   */
  public static void testGetConstructor() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據(jù)class,獲取構(gòu)造函數(shù)
      //Constructor cst1 = cls.getConstructor(); // 拋出異常,因為默認(rèn)構(gòu)造函數(shù)是private權(quán)限。
      //Constructor cst2 = cls.getConstructor(new Class[]{String.class});// 拋出異常,因為該構(gòu)造函數(shù)是protected權(quán)限。
      Constructor cst3 = cls.getConstructor(new Class[]{String.class, int.class, Gender.class});
      // 根據(jù)構(gòu)造函數(shù),創(chuàng)建相應(yīng)的對象
      //Object p1 = cst1.newInstance();
      //cst1.setAccessible(true); // 因為Person中Person()是private的,所以這里要設(shè)置為可訪問
      //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() 的測試函數(shù)
   */
  public static void testGetEnclosingConstructor() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據(jù)class,調(diào)用Person類中有內(nèi)部類InnerA的構(gòu)造函數(shù)
      Constructor cst = cls.getDeclaredConstructor(new Class[]{String.class, int.class});
      // 根據(jù)構(gòu)造函數(shù),創(chuàng)建相應(yīng)的對象
      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;
    //內(nèi)部類在構(gòu)造方法中
    class InnerA{
    }
    // 獲取InnerA的Class對象
    Class cls = InnerA.class;

    // 獲取“封閉該內(nèi)部類(InnerA)”的構(gòu)造方法
    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()的參數(shù)必須是,Person類的完整包名。
運行結(jié)果:

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() 的測試函數(shù)”。getDeclaredConstructor()可以“獲取類中任意的構(gòu)造函數(shù),包含public、protected和private方法”。

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

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

2.2 成員方法

 “成員方法”相關(guān)API

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

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

package com.bjpowernode.test;
import java.lang.Class;
import java.lang.reflect.Method;
/**
 * java Class類的Method相關(guān)API的測試函數(shù)
 *
 * 
 */
public class DemoClassMethod {
  public static void main(String[] args) {
      // getDeclaredMethod() 的測試函數(shù)
      testGetDeclaredMethod() ;
      // getMethod() 的測試函數(shù)
      testGetMethod() ;
      // getEnclosingMethod() 的測試函數(shù)
      testGetEnclosingMethod() ;
  }
  /**
   * getDeclaredMethod() 的測試函數(shù)
   */
  public static void testGetDeclaredMethod() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據(jù)class,調(diào)用類的默認(rèn)構(gòu)造函數(shù)(不帶參數(shù))
      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[]{});
      // 調(diào)用獲取的方法
      mSetName.invoke(person, new Object[]{"Jimmy"});
      mSetAge.invoke(person, new Object[]{30});
      mSetGender.setAccessible(true);  // 因為Person中setGender()是private的,所以這里要設(shè)置為可訪問
      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中g(shù)etGender()是private的,所以這里要設(shè)置為可訪問
      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() 的測試函數(shù)
   */
  public static void testGetMethod() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據(jù)class,調(diào)用類的默認(rèn)構(gòu)造函數(shù)(不帶參數(shù))
      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權(quán)限。
      //Method mGetAge = cls.getMethod("getAge", new Class[]{});         // 拋出異常,因為getAge()是protected權(quán)限。
      //Method mSetGender = cls.getMethod("setGender", new Class[]{Gender.class}); // 拋出異常,因為setGender()是private權(quán)限。
      //Method mGetGender = cls.getMethod("getGender", new Class[]{});       // 拋出異常,因為getGender()是private權(quán)限。
      // 調(diào)用獲取的方法
      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() 的測試函數(shù)
   */
  public static void testGetEnclosingMethod() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據(jù)class,調(diào)用類的默認(rèn)構(gòu)造函數(shù)(不帶參數(shù))
      Object person = cls.newInstance();
      // 根據(jù)class,調(diào)用Person類中有內(nèi)部類InnerB的函數(shù)
      Method mGetInner = cls.getDeclaredMethod("getInner", new Class[]{});
      // 根據(jù)構(gòu)造函數(shù),創(chuàng)建相應(yīng)的對象
      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;
  }
  // 獲取”姓名“。權(quán)限是 public
  public String getName() {
    return name;
  }
  // 設(shè)置”姓名“。權(quán)限是 public
  public void setName(String name) {
    this.name = name;
  }
  // 獲取”年齡“。權(quán)限是 protected
  protected int getAge() {
    return age;
  }
  // 設(shè)置”年齡“。權(quán)限是 protected
  protected void setAge(int age) {
    this.age = age;
  }
  // 獲取“性別”。權(quán)限是 private
  private Gender getGender() {
    return gender;
  }
  // 設(shè)置“性別”。權(quán)限是 private
  private void setGender(Gender gender) {
    this.gender = gender;
  }
  // getInner() 中有內(nèi)部類InnerB,用來測試getEnclosingMethod()
  public void getInner() {
    // 內(nèi)部類
    class InnerB{
    }
    // 獲取InnerB的Class對象
    Class cls = InnerB.class;
    // 獲取“封閉該內(nèi)部類(InnerB)”的構(gòu)造方法
    Method cst = cls.getEnclosingMethod();
    System.out.println("call--\"getInner()\" cst="+cst);
  }
  @Override
  public String toString() {
    return "("+name+", "+age+", "+gender+")";
  }
}

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

運行結(jié)果:

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 成員變量

“成員變量”的相關(guān)API

// 獲取“名稱是name”的public的成員變量(包括從基類繼承的、從接口實現(xiàn)的所有public成員變量)
public Field  getField(String name)
// 獲取全部的public成員變量(包括從基類繼承的、從接口實現(xiàn)的所有public成員變量)
public Field[]  getFields()
// 獲取“名稱是name”,并且是類自身聲明的成員變量,包含public、protected和private成員變量。
public Field  getDeclaredField(String name)
// 獲取全部的類自身聲明的成員變量,包含public、protected和private成員變量。
public Field[]  getDeclaredFields()
接下來,我們通過示例對這些API進(jìn)行說明。示例代碼(DemoClassField.java)如下:
package com.bjpowernode.test;
import java.lang.Class;
import java.lang.reflect.Field;
/**
 * java Class類的"成員變量"相關(guān)API的測試函數(shù)
 *
 * 
 */
public class DemoClassField {
  public static void main(String[] args) {
    // getDeclaredField() 的測試函數(shù)
    testGetDeclaredField() ;
    // getField() 的測試函數(shù)
    testGetField() ;
  }
  /**
   * getDeclaredField() 的測試函數(shù)
   * getDeclaredField() 用于獲取的是類自身聲明的所有成員遍歷,包含public、protected和private方法。
   */
  public static void testGetDeclaredField() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據(jù)class,調(diào)用類的默認(rèn)構(gòu)造函數(shù)(不帶參數(shù))
      Object person = cls.newInstance();
      // 根據(jù)class,獲取Filed
      Field fName = cls.getDeclaredField("name");
      Field fAge = cls.getDeclaredField("age");
      Field fGender = cls.getDeclaredField("gender");
      // 根據(jù)構(gòu)造函數(shù),創(chuàng)建相應(yīng)的對象
      fName.set(person, "Hamier");
      fAge.set(person, 31);
      fGender.setAccessible(true); // 因為"flag"是private權(quán)限,所以要設(shè)置訪問權(quán)限為true;否則,會拋出異常。
      fGender.set(person, Gender.FEMALE);
      System.out.printf("%-30s: person=%s\n", 
          "getDeclaredField()", person);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  /**
   * getField() 的測試函數(shù)
   * getField() 用于獲取的是public的“成員”
   */
  public static void testGetField() {
    try {
      // 獲取Person類的Class
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 根據(jù)class,調(diào)用類的默認(rèn)構(gòu)造函數(shù)(不帶參數(shù))
      Object person = cls.newInstance();
      // 根據(jù)class,獲取Filed
      Field fName = cls.getField("name");
      Field fAge = cls.getDeclaredField("age");    // 拋出異常,因為Person中age是protected權(quán)限。 
      Field fGender = cls.getDeclaredField("gender"); // 拋出異常,因為Person中g(shù)ender是private權(quán)限。 
      // 根據(jù)構(gòu)造函數(shù),創(chuàng)建相應(yīng)的對象
      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()的參數(shù)必須是,Person類的完整包名。

運行結(jié)果:

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

2.4 類的其它信息

2.4.1 “注解”相關(guān)的API

// 獲取類的"annotationClass"類型的注解 (包括從基類繼承的、從接口實現(xiàn)的所有public成員變量)
public Annotation<A>  getAnnotation(Class annotationClass)
// 獲取類的全部注解 (包括從基類繼承的、從接口實現(xiàn)的所有public成員變量)
public Annotation[]  getAnnotations()
// 獲取類自身聲明的全部注解 (包含public、protected和private成員變量)
public Annotation[]  getDeclaredAnnotations()
接下來,我們通過示例對這些API進(jìn)行說明。示例代碼(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 {
      // 根據(jù)“類名”獲取 對應(yīng)的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()的參數(shù)必須是,Person類的完整包名。

運行結(jié)果:

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

說明:

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

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

1.1.1.1

2.4.2 “父類”和“接口”相關(guān)的API

// 獲取實現(xiàn)的全部接口
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類的有關(guān)父類和接口的測試
 */
public class DemoClassInterface {
  public static void main(String[] args) {
    try {
      // 根據(jù)“類名”獲取 對應(yīng)的Class對象
      Class<?> cls = Class.forName("com.bjpowernode.test.Person");
      // 獲取“Person”的父類
      Type father = cls.getGenericSuperclass();
      // 獲取“Person”實現(xiàn)的全部接口
      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,并且實現(xiàn)了Serializable和Runnable接口
 */
class Person extends Object implements Serializable, Runnable{
  @Override
  public void run() {
  }
}

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

運行結(jié)果:

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()
// 類是不是“本地類”。本地類,就是定義在方法內(nèi)部的類。
public boolean  isLocalClass()
// 類是不是“成員類”。成員類,是內(nèi)部類的一種,但是它不是“內(nèi)部類”或“匿名類”。
public boolean  isMemberClass()
// 類是不是“基本類型”。 基本類型,包括void和boolean、byte、char、short、int、long、float 和 double這幾種類型。
public boolean  isPrimitive()
// 類是不是“復(fù)合類”。 JVM中才會產(chǎn)生復(fù)合類,在java應(yīng)用程序中不存在“復(fù)合類”!
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());
    // 類是不是“本地類”。本地類,就是定義在方法內(nèi)部的類。
    Class localCls = LocalA.class;
    System.out.printf("%-50s:isLocalClass()=%s\n", 
        localCls, localCls.isLocalClass());
    // 類是不是“成員類”。成員類,是內(nèi)部類的一種,但是它不是“內(nèi)部類”或“匿名類”。
    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());
    // 類是不是“復(fù)合類”。 JVM中才會產(chǎn)生復(fù)合類,在java應(yīng)用程序中不存在“復(fù)合類”!
    Class synCls = DemoClassOtherAPIs.class;
    System.out.printf("%-50s:isSynthetic()=%s\n", 
        synCls, synCls.isSynthetic());
  }
  // 內(nèi)部成員類
  class MemberB {
  }
}

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

運行結(jié)果:

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是不是“復(fù)合類”。這在java應(yīng)用程序中只會返回false,不會返回true。因為,JVM中才會產(chǎn)生復(fù)合類,在java應(yīng)用程序中不存在“復(fù)合類”!

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

相關(guān)文章

  • Maven離線模式打包全過程

    Maven離線模式打包全過程

    這篇文章主要介紹了Maven離線模式打包全過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • java IP地址網(wǎng)段計算的示例代碼

    java IP地址網(wǎng)段計算的示例代碼

    這篇文章主要介紹了java IP地址網(wǎng)段計算的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Eclipse+Java+Swing+Mysql實現(xiàn)工資管理系統(tǒng)

    Eclipse+Java+Swing+Mysql實現(xiàn)工資管理系統(tǒng)

    這篇文章主要介紹了Eclipse+Java+Swing+Mysql實現(xiàn)工資管理系統(tǒng),對正在工作或者學(xué)習(xí)的你有一定的參考價值,需要的朋友可以參考一下
    2022-01-01
  • Java封裝、繼承、多態(tài)三大特征的理解

    Java封裝、繼承、多態(tài)三大特征的理解

    封裝、繼承、多態(tài)三大特征是java中比較常用的,務(wù)必要掌握,下面給大家介紹Java封裝、繼承、多態(tài)三大特征的理解,有不清楚的朋友可以一起學(xué)習(xí)下
    2016-06-06
  • java檢查數(shù)組是否有重復(fù)元素的方法

    java檢查數(shù)組是否有重復(fù)元素的方法

    這篇文章主要介紹了java檢查數(shù)組是否有重復(fù)元素的方法,涉及java針對數(shù)組元素的操作技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • eclipse漢化及jdk安裝環(huán)境配置超詳細(xì)教程(Java安裝教程)

    eclipse漢化及jdk安裝環(huán)境配置超詳細(xì)教程(Java安裝教程)

    這篇文章主要介紹了eclipse漢化及jdk安裝環(huán)境配置超詳細(xì)教程(Java安裝教程),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • Elasticsearch模糊查詢詳細(xì)介紹

    Elasticsearch模糊查詢詳細(xì)介紹

    這篇文章主要給大家介紹了關(guān)于Elasticsearch模糊查詢的相關(guān)資料,在數(shù)據(jù)庫查詢中模糊查詢是一種強大的技術(shù),可以用來搜索與指定模式匹配的數(shù)據(jù),需要的朋友可以參考下
    2023-09-09
  • spring整合cxf框架實例

    spring整合cxf框架實例

    下面小編就為大家?guī)硪黄猻pring整合cxf框架實例。小編覺得挺不錯的?,F(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • Java模擬登錄正方教務(wù)抓取成績、課表、空教室

    Java模擬登錄正方教務(wù)抓取成績、課表、空教室

    這篇文章主要介紹了Java模擬登錄正方教務(wù)抓取成績、課表、空教室等信息,Java實現(xiàn)模擬登錄正方教務(wù)抓取成績、課表、空教室,通過HttpClient來模擬瀏覽器請求,Jsoup解析網(wǎng)頁內(nèi)容,感興趣的小伙伴們可以參考一下
    2016-04-04
  • 使用Java實現(xiàn)動態(tài)生成MySQL數(shù)據(jù)庫

    使用Java實現(xiàn)動態(tài)生成MySQL數(shù)據(jù)庫

    這篇文章主要為大家詳細(xì)介紹了如何使用Java實現(xiàn)動態(tài)生成MySQL數(shù)據(jù)庫,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02

最新評論