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

Java反射簡(jiǎn)易教程

 更新時(shí)間:2017年11月13日 14:15:55   作者:TCP/IP協(xié)議棧學(xué)習(xí)ing  
這篇文章主要介紹了Java反射簡(jiǎn)易教程,小編覺(jué)得挺不錯(cuò)的,這里分享給大家,需要的朋友可以參考。

關(guān)于Java反射,我們需要弄懂以下幾個(gè)問(wèn)題:

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

下面我們來(lái)一一進(jìn)行講解:

一、反射是什么?

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

Java反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性及方法;對(duì)于任何一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法;這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為Java的反射機(jī)制。

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

反射經(jīng)常和自省弄混,為了區(qū)別,我們先看看兩者的詳細(xì)定義:

自省(Introspection):

Introspectionistheabilityofaprogramtoexaminethetypeorpropertiesof

anobjectatruntime.

反射(Reflection):

Reflectionistheabilityofaprogramtoexamineandmodifythestructure

andbehaviorofanobjectatruntime.

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

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

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

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

反射實(shí)例: Class.forName()方法返回了一個(gè)具體類/接口的對(duì)象,當(dāng)然參數(shù)需要指定為特定的類名。

// 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反射在框架開(kāi)發(fā)中尤為重要。有些情況下,我們要使用的類在運(yùn)行時(shí)才會(huì)確定,這個(gè)時(shí)候我們不能在編譯期就使用它,因此只能通過(guò)反射的形式來(lái)使用在運(yùn)行時(shí)才存在的類(該類符合某種特定的規(guī)范,例如JDBC),這是反射用得比較多的場(chǎng)景。

編譯時(shí)我們對(duì)于類的內(nèi)部信息不可知,必須得到運(yùn)行時(shí)才能獲取類的具體信息。比如ORM框架,在運(yùn)行時(shí)才能夠獲取類中的各個(gè)屬性,然后通過(guò)反射的形式獲取其屬性名和值,存入數(shù)據(jù)庫(kù)。

反射機(jī)制提供的功能:

在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類; 在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象; 在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法; 在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法。通過(guò)反射甚至可以調(diào)用到private的方法; 在運(yùn)行時(shí)修改構(gòu)造函數(shù),變量和方法的訪問(wèn)權(quán)限。

解耦

假如我們有兩個(gè)程序員,一個(gè)程序員在寫(xiě)程序的時(shí)候,需要使用第二個(gè)程序員所寫(xiě)的類,但第二個(gè)程序員并沒(méi)完成他所寫(xiě)的類。那么第一個(gè)程序員的代碼能否通過(guò)編譯呢?這是不能通過(guò)編譯的。利用Java反射的機(jī)制,就可以讓第一個(gè)程序員在沒(méi)有得到第二個(gè)程序員所寫(xiě)的類的時(shí)候,來(lái)完成自身代碼的編譯

在對(duì)類的調(diào)用和實(shí)例化的時(shí)候,通過(guò)在配置文件中配置相應(yīng)的類名,在程序中讀取類名,然后通過(guò)反射技術(shù)在程序中加載和實(shí)例化,如常見(jiàn)的數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序類,為了達(dá)到不依賴特定數(shù)據(jù)庫(kù)驅(qū)動(dòng)類,將用到的數(shù)據(jù)庫(kù)驅(qū)動(dòng)類名放到配置文件中(常用的有XML文件、Properties文件和文本文件),然后在程序中加載驅(qū)動(dòng),來(lái)實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的解耦,也就是說(shuō)只要修改配置文件,就可以方便地更改數(shù)據(jù)庫(kù)類型。

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

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

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

這種機(jī)制同樣也用于Servlet的web應(yīng)用:

<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反射相關(guān)類

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

Class類:Class類的實(shí)例表示正在運(yùn)行的Java應(yīng)用程序中的類和接口。Field類:提供有關(guān)類或接口的屬性的信息,以及對(duì)它的動(dòng)態(tài)訪問(wèn)權(quán)限。反射的字段可能是一個(gè)類屬性或?qū)嵗龑傩裕?jiǎn)單的理解可以把它看成一個(gè)封裝反射類的屬性的類。Constructor類:提供關(guān)于類的單個(gè)構(gòu)造方法的信息以及對(duì)它的訪問(wèn)權(quán)限。這個(gè)類和Field類不同,F(xiàn)ield類封裝了反射類的屬性,而Constructor類則封裝了反射類的構(gòu)造方法。Method類:提供關(guān)于類或接口上單獨(dú)某個(gè)方法的信息。所反映的方法可能是類方法或?qū)嵗椒ǎòǔ橄蠓椒ǎ?。這個(gè)類不難理解,它是用來(lái)封裝反射類方法的一個(gè)類。Array類:提供了動(dòng)態(tài)創(chuàng)建數(shù)組和訪問(wèn)數(shù)組的靜態(tài)方法。該類中的所有方法都是靜態(tài)方法。

Class

類是程序的一部分,每個(gè)類都有一個(gè)Class對(duì)象。換言之,每當(dāng)編寫(xiě)并且編譯了一個(gè)新類,就會(huì)產(chǎn)生一個(gè)Class對(duì)象。

Class沒(méi)有公共構(gòu)造方法。Class對(duì)象是在加載類時(shí)由Java虛擬機(jī)以及通過(guò)調(diào)用類加載器中的defineClass方法自動(dòng)構(gòu)造的,因此不能顯式地聲明一個(gè)Class對(duì)象

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

Class的方法

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

Constructor

獲得類的構(gòu)造方法

ConstructorgetConstructor(Class[]params)–獲得使用特殊的參數(shù)類型的公共構(gòu)造函數(shù)Constructor[]getConstructors()–獲得類的所有公共構(gòu)造函數(shù)ConstructorgetDeclaredConstructor(Class[]params)–獲得使用特定參數(shù)類型的構(gòu)造函數(shù)(與接入級(jí)別無(wú)關(guān))Constructor[]getDeclaredConstructors()–獲得類的所有構(gòu)造函數(shù)(與接入級(jí)別無(wú)關(guān))

Field

獲取類定義變量

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

Method

獲取類定義方法

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

四、反射怎么用?

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

Example1:從對(duì)象中獲取類名

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: 調(diào)用未知對(duì)象的方法

想象我們不知道一個(gè)對(duì)象的類型,但是通過(guò)反射,我們可以使用這個(gè)對(duì)象并且找到這個(gè)對(duì)象是否有個(gè)方法名叫print并且調(diào)用它,如下所示:

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實(shí)例創(chuàng)建對(duì)象

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: 獲取構(gòu)造器并創(chuàng)建實(shí)例

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實(shí)例并獲取實(shí)現(xiàn)的接口,父類,聲明的方法等。

Example 5: 通過(guò)反射修改數(shù)組大小

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

五、 總結(jié)

本文只是對(duì)Java反射很小的內(nèi)容進(jìn)行了講解,大家有興趣了解更多信息可以從網(wǎng)絡(luò)查找資料。

以上就是本文關(guān)于Java反射簡(jiǎn)易教程的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:關(guān)于Java反射機(jī)制 你需要知道的事情、Java的RTTI和反射機(jī)制代碼分析等,有什么問(wèn)題可以隨時(shí)留言,小編會(huì)及時(shí)回復(fù)大家的。感謝朋友們對(duì)本站的支持!

相關(guān)文章

  • SpringBoot結(jié)合Tess4J實(shí)現(xiàn)拍圖識(shí)字的示例代碼

    SpringBoot結(jié)合Tess4J實(shí)現(xiàn)拍圖識(shí)字的示例代碼

    圖片中的文字提取已經(jīng)越來(lái)越多地應(yīng)用于數(shù)據(jù)輸入和自動(dòng)化處理過(guò)程,本文主要介紹了SpringBoot結(jié)合Tess4J實(shí)現(xiàn)拍圖識(shí)字的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-06-06
  • springboot中的RestTemplate使用詳解

    springboot中的RestTemplate使用詳解

    這篇文章主要介紹了springboot中的RestTemplate使用詳解,RestTemplate繼承自InterceptingHttpAccessor并且實(shí)現(xiàn)了RestOperations接口,其中RestOperations接口定義了基本的RESTful操作,這些操作在RestTemplate中都得到了實(shí)現(xiàn),需要的朋友可以參考下
    2023-09-09
  • SpringBoot深入講解單元測(cè)試與熱部署應(yīng)用

    SpringBoot深入講解單元測(cè)試與熱部署應(yīng)用

    這篇文章介紹了SpringBoot單元測(cè)試與熱部署,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • java實(shí)現(xiàn)隊(duì)列queue數(shù)據(jù)結(jié)構(gòu)詳解

    java實(shí)現(xiàn)隊(duì)列queue數(shù)據(jù)結(jié)構(gòu)詳解

    大家好,本篇文章主要講的是java實(shí)現(xiàn)隊(duì)列queue數(shù)據(jù)結(jié)構(gòu)詳解,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-02-02
  • Java中分割字符串的兩種方法實(shí)例詳解

    Java中分割字符串的兩種方法實(shí)例詳解

    這篇文章主要介紹了Java中分割字符串的兩種方法,一種是java.lang.String 的 split() 方法,,另外一種是用String Tokenizer類。文中的每種方法都給出了詳細(xì)的示例代碼,相信對(duì)大家的理解和學(xué)習(xí)具有一定的參考借鑒價(jià)值,有需要的朋友們下面來(lái)一起看看吧。
    2016-12-12
  • Springboot?RestTemplate設(shè)置超時(shí)時(shí)間的簡(jiǎn)單方法

    Springboot?RestTemplate設(shè)置超時(shí)時(shí)間的簡(jiǎn)單方法

    學(xué)習(xí)springboot ,RestTemplate的使用場(chǎng)景非常非常多,比如springcloud中的服務(wù)消費(fèi),下面這篇文章主要給大家介紹了關(guān)于Springboot?RestTemplate設(shè)置超時(shí)時(shí)間的簡(jiǎn)單方法,需要的朋友可以參考下
    2022-01-01
  • SpringSecurity自定義成功失敗處理器的示例代碼

    SpringSecurity自定義成功失敗處理器的示例代碼

    這篇文章主要介紹了SpringSecurity自定義成功失敗處理器,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • springboot layui hutool Excel導(dǎo)入的實(shí)現(xiàn)

    springboot layui hutool Excel導(dǎo)入的實(shí)現(xiàn)

    本文主要介紹了springboot layui hutool Excel導(dǎo)入的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-03-03
  • java實(shí)現(xiàn)郵件發(fā)送詳解

    java實(shí)現(xiàn)郵件發(fā)送詳解

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)郵件發(fā)送示例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • java判斷兩個(gè)時(shí)間是不是同一天的方法

    java判斷兩個(gè)時(shí)間是不是同一天的方法

    這篇文章主要介紹了java判斷兩個(gè)時(shí)間是不是同一天的方法,需要的朋友可以參考下
    2014-02-02

最新評(píng)論