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

溫馨提示×

溫馨提示×

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

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

Java反射簡易教程

發布時間:2020-09-29 21:15:05 來源:腳本之家 閱讀:122 作者:TCP/IP協議棧學習ing 欄目:編程語言

關于Java反射,我們需要弄懂以下幾個問題:

反射是什么?反射有什么用?怎么用反射?

下面我們來一一進行講解:

一、反射是什么?

Reflection的意思是“反射、映象、倒影”,用在Java身上指的是我們可以于運行時加載、探知、使用編譯期間完全未知的classes。換句話說,Java程序可以加載一個運行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),并生成其對象實體、或對其fields設值、或喚起其methods。

Java反射機制是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性及方法;對于任何一個對象,都能夠調用它的任意一個方法;這種動態獲取信息以及動態調用對象的方法的功能稱為Java的反射機制。

1.自省(Introspection)vs.反射(Reflection)

反射經常和自省弄混,為了區別,我們先看看兩者的詳細定義:

自省(Introspection):

Introspectionistheabilityofaprogramtoexaminethetypeorpropertiesof

anobjectatruntime.

反射(Reflection):

Reflectionistheabilityofaprogramtoexamineandmodifythestructure

andbehaviorofanobjectatruntime.

從上述定義,我們可以看出,自省是反射的子集。部分語言支持自省,但是不支持反射,比如C++。

2.自省示例vs.反射示例

自省示例:instanceof操作符用于判斷一個對象是否屬于一個特定的類。

if(obj instanceof Dog) {
  Dog d = (Dog)obj;
  d.bark();
}

反射實例: Class.forName()方法返回了一個具體類/接口的對象,當然參數需要指定為特定的類名。

// with reflection
Class <!--?--> c = Class.forName("classpath.and.classname");
Object dog = c.newInstance();
 
Method m = c.getDeclaredMethod("bark", new Class<!--?-->[0]);
m.invoke(dog);

二、 為什么需要反射?

Java反射在框架開發中尤為重要。有些情況下,我們要使用的類在運行時才會確定,這個時候我們不能在編譯期就使用它,因此只能通過反射的形式來使用在運行時才存在的類(該類符合某種特定的規范,例如JDBC),這是反射用得比較多的場景。

編譯時我們對于類的內部信息不可知,必須得到運行時才能獲取類的具體信息。比如ORM框架,在運行時才能夠獲取類中的各個屬性,然后通過反射的形式獲取其屬性名和值,存入數據庫。

反射機制提供的功能:

在運行時判斷任意一個對象所屬的類; 在運行時構造任意一個類的對象; 在運行時判斷任意一個類所具有的成員變量和方法; 在運行時調用任意一個對象的方法。通過反射甚至可以調用到private的方法; 在運行時修改構造函數,變量和方法的訪問權限。

解耦

假如我們有兩個程序員,一個程序員在寫程序的時候,需要使用第二個程序員所寫的類,但第二個程序員并沒完成他所寫的類。那么第一個程序員的代碼能否通過編譯呢?這是不能通過編譯的。利用Java反射的機制,就可以讓第一個程序員在沒有得到第二個程序員所寫的類的時候,來完成自身代碼的編譯

在對類的調用和實例化的時候,通過在配置文件中配置相應的類名,在程序中讀取類名,然后通過反射技術在程序中加載和實例化,如常見的數據庫驅動程序類,為了達到不依賴特定數據庫驅動類,將用到的數據庫驅動類名放到配置文件中(常用的有XML文件、Properties文件和文本文件),然后在程序中加載驅動,來實現對數據庫的解耦,也就是說只要修改配置文件,就可以方便地更改數據庫類型。

例如, Spring使用如下的bean配置:

<bean class="com.programcreek.Foo" id="someID">
<property name="someField" value="someValue">
</property></bean>

當Spring在處理時,會使用Class.forName(String),同時參數為"com.xxx.Foo"用于實例化這個Class。同時,使用反射設置去用于設置特定的值。

這種機制同樣也用于Servlet的web應用:

<code><code><code><code><code><code><servlet>
<servlet name="">someServlet 
<servlet>com.programcreek.WhyReflectionServlet</servlet>
<servlet data-filtered="filtered"></servlet></servlet></servlet></code></code></code></code></code></code>

三、反射API

Java反射相關類

Java反射所需要的類并不多,主要有java.lang.Class類java.lang.reflect包中的Field、Constructor、Method、Array類,簡單說明如下所示:

Class類:Class類的實例表示正在運行的Java應用程序中的類和接口。Field類:提供有關類或接口的屬性的信息,以及對它的動態訪問權限。反射的字段可能是一個類屬性或實例屬性,簡單的理解可以把它看成一個封裝反射類的屬性的類。Constructor類:提供關于類的單個構造方法的信息以及對它的訪問權限。這個類和Field類不同,Field類封裝了反射類的屬性,而Constructor類則封裝了反射類的構造方法。Method類:提供關于類或接口上單獨某個方法的信息。所反映的方法可能是類方法或實例方法(包括抽象方法)。這個類不難理解,它是用來封裝反射類方法的一個類。Array類:提供了動態創建數組和訪問數組的靜態方法。該類中的所有方法都是靜態方法。

Class

類是程序的一部分,每個類都有一個Class對象。換言之,每當編寫并且編譯了一個新類,就會產生一個Class對象。

Class沒有公共構造方法。Class對象是在加載類時由Java虛擬機以及通過調用類加載器中的defineClass方法自動構造的,因此不能顯式地聲明一個Class對象

Class是Reflection的起源。要想操縱;類的屬性和方法,都必須從獲取ClassObject開始。

Class的方法

getName():獲得類的完整名字。getFields():獲得類的public類型的屬性。getDeclaredFields():獲得類的所有屬性。getMethods():獲得類的public類型的方法。getDeclaredMethods():獲得類的所有方法。getMethod(Stringname,Class[]parameterTypes):獲得類的特定方法,name參數指定方法的名字,–parameterTypes參數指定方法的參數類型。getConstrutors():獲得類的public類型的構造方法。getConstrutor(Class[]parameterTypes):獲得類的特定構造方法,parameterTypes參數指定構造方法的參數類型。newInstance():通過類的不帶參數的構造方法創建這個類的一個對象。

Constructor

獲得類的構造方法

ConstructorgetConstructor(Class[]params)–獲得使用特殊的參數類型的公共構造函數Constructor[]getConstructors()–獲得類的所有公共構造函數ConstructorgetDeclaredConstructor(Class[]params)–獲得使用特定參數類型的構造函數(與接入級別無關)Constructor[]getDeclaredConstructors()–獲得類的所有構造函數(與接入級別無關)

Field

獲取類定義變量

FieldgetField(Stringname)–獲得命名的公共字段Field[]getFields()–獲得類的所有公共字段FieldgetDeclaredField(Stringname)–獲得類聲明的命名的字段Field[]getDeclaredFields()–獲得類聲明的所有字段

Method

獲取類定義方法

MethodgetMethod(Stringname,Class[]params)–使用特定的參數類型,獲得命名的公共方法Method[]getMethods()–獲得類的所有公共方法MethodgetDeclaredMethod(Stringname,Class[]params)–使用特寫的參數類型,獲得類聲明的命名的方法Method[]getDeclaredMethods()–獲得類聲明的所有方法

四、反射怎么用?

上一章我們講解了Java反射API,那么這一章我們將用一些代碼實例來展示如何使用這些反射API。

Example1:從對象中獲取類名

package com.longluo.java.interview.reflection;
 
public class ReflectionHelloWorld {
 
  public static void main(String[] args) {
    Foo f = new Foo();
    System.out.println(f.getClass().getName());
  }
}
 
class Foo {
  public void print() {
    System.out.println("abc");
  }
}

輸出:

com.longluo.java.interview.reflection.Foo

Example 2: 調用未知對象的方法

想象我們不知道一個對象的類型,但是通過反射,我們可以使用這個對象并且找到這個對象是否有個方法名叫print并且調用它,如下所示:

package com.longluo.java.interview.reflection;
 
import java.lang.reflect.Method;
 
public class ReflectionHelloWorld {
 
  /*
   * public static void main(String[] args) { Foo f = new Foo();
   * System.out.println(f.getClass().getName()); }
   */
 
  public static void main(String[] args) {
    Foo f = new Foo();
    Method method;
    try {
      method = f.getClass().getMethod("print", new Class<!--?-->[0]);
      method.invoke(f);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
 
}
 
class Foo {
  public void print() {
    System.out.println("abc");
  }
}

輸出:

abc

Example 3: 從Class實例創建對象

package com.longluo.java.interview.reflection;
 
import java.lang.reflect.Method;
 
public class ReflectionHelloWorld {
 
  public static void main(String[] args) {
    // create instance of "Class"
 
    Class<!--?--> c = null;
 
    try {
      c = Class.forName("com.longluo.java.interview.reflection.Foo");
 
    } catch (Exception e) {
      e.printStackTrace();
    }
 
    // create instance of "Foo"
    Foo f = null;
    try {
      f = (Foo) c.newInstance();
    } catch (Exception e) {
      e.printStackTrace();
    }
    f.print();
  }
 
}
 
class Foo {
  public void print() {
    System.out.println("abc");
  }
}

Example 4: 獲取構造器并創建實例

package com.longluo.java.interview.reflection;
import java.lang.reflect.Constructor;
public class ReflectionHelloWorld4 {
  public static void main(String[] args) {
    // create instance of "Class"
    Class<!--?--> c = null;
    try {
      c = Class.forName("com.longluo.java.interview.reflection.Foo4");
    } catch (Exception e) {
      e.printStackTrace();
    }
    // create instance of "Foo"
    Foo4 f1 = null;
    Foo4 f2 = null;
    // get all constructors
    Constructor<!--?--> cons[] = c.getConstructors();
    try {
      f1 = (Foo4) cons[0].newInstance();
      f2 = (Foo4) cons[1].newInstance("abc");
    } catch (Exception e) {
      e.printStackTrace();
    }
    f1.print();
    f2.print();
  }
}
class Foo4 {
  String s;
  public Foo4() {
  }
  public Foo4(String s) {
    this.s = s;
  }
  public void print() {
    System.out.println(s);
  }
}

輸出:

null
abc

另外,你可以使用Class實例并獲取實現的接口,父類,聲明的方法等。

Example 5: 通過反射修改數組大小

package com.longluo.java.interview.reflection;
import java.lang.reflect.Array;
public class ReflectionHelloWorld5 {
  public static void main(String[] args) {
    int[] intArray = { 1, 2, 3, 4, 5 };
    int[] newIntArray = (int[]) changeArraySize(intArray, 10);
    print(newIntArray);
    String[] atr = { "a", "b", "c", "d", "e" };
    String[] str1 = (String[]) changeArraySize(atr, 10);
    print(str1);
  }
  // change array size
  public static Object changeArraySize(Object obj, int len) {
    Class<!--?--> arr = obj.getClass().getComponentType();
    Object newArray = Array.newInstance(arr, len);
    // do array copy
    int co = Array.getLength(obj);
    System.arraycopy(obj, 0, newArray, 0, co);
    return newArray;
  }
  // print
  public static void print(Object obj) {
    Class<!--?--> c = obj.getClass();
    if (!c.isArray()) {
      return;
    }
    System.out.println("\nArray length:" + Array.getLength(obj));
    for (int i = 0; i < Array.getLength(obj); i++) {
      System.out.print(Array.get(obj, i) + " ");
    }
  }
}

輸出:

Array length:10
1 2 3 4 5 0 0 0 0 0
Array length:10
a b c d e null null null null null

五、 總結

本文只是對Java反射很小的內容進行了講解,大家有興趣了解更多信息可以從網絡查找資料。

以上就是本文關于Java反射簡易教程的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站:關于Java反射機制 你需要知道的事情、Java的RTTI和反射機制代碼分析等,有什么問題可以隨時留言,小編會及時回復大家的。感謝朋友們對本站的支持!

向AI問一下細節

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

AI

新竹市| 长顺县| 政和县| 屏东县| 隆子县| 维西| 金沙县| 贵阳市| 连江县| 奇台县| 福州市| 滦平县| 蕉岭县| 读书| 来宾市| 花莲市| 瓦房店市| 习水县| 和硕县| 凤城市| 浮梁县| 分宜县| 昌邑市| 福海县| 台北县| 兴义市| 德保县| 金溪县| 介休市| 武强县| 宜兰县| 平远县| 定襄县| 旬邑县| 漳州市| 沽源县| 文昌市| 太仓市| 隆子县| 武汉市| 唐海县|