最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入淺析Java反射機(jī)制

 更新時(shí)間:2015年11月06日 11:31:06   投稿:mrr  
Java反射機(jī)制是在運(yùn)行狀態(tài)中,對于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對于任意一個(gè)對象,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對象的方法的功能稱為Java語言的反射機(jī)制

Java反射機(jī)制是在運(yùn)行狀態(tài)中,對于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對于任意一個(gè)對象,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對象的方法的功能稱為Java語言的反射機(jī)制。反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問、檢測和修改它本身狀態(tài)或行為的一種能力。這一概念的提出很快引發(fā)了計(jì)算機(jī)科學(xué)領(lǐng)域關(guān)于應(yīng)用反射性的研究。它首先被程序語言的設(shè)計(jì)領(lǐng)域所采用,并在Lisp和面向?qū)ο蠓矫嫒〉昧顺煽儭.?dāng)然反射本身并不是一個(gè)新概念,它可能會(huì)使我們聯(lián)想到光學(xué)中的反射概念,盡管計(jì)算機(jī)科學(xué)賦予了反射概念新的含義,但是,從現(xiàn)象上來說,它們確實(shí)有某些相通之處,這些有助于我們的理解。

      Java反射機(jī)制主要提供下面幾種用途:

在運(yùn)行時(shí)判斷任意一個(gè)對象所屬的類

在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對象

在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法

在運(yùn)行時(shí)調(diào)用任意一個(gè)對象的方法

首先看一個(gè)簡單的例子,通過這個(gè)例子來理解Java的反射機(jī)制是如何工作的。

package com.wanggc.reflection;
import java.lang.reflect.Method;
/**
 * Java 反射練習(xí)。
 * 
 * @author Wanggc
 */
public class ForNameTest {
  /**
   * 入口函數(shù)。
   * 
   * @param args
   *      參數(shù)
   * @throws Exception
   *       錯(cuò)誤信息
   */
  public static void main(String[] args) throws Exception {
    // 獲得Class
    Class<?> cls = Class.forName(args[0]);
    // 通過Class獲得所對應(yīng)對象的方法
    Method[] methods = cls.getMethods();
    // 輸出每個(gè)方法名
    for (Method method : methods) {
      System.out.println(method);
    }
  }
}

      當(dāng)傳入的參數(shù)是java.lang.String時(shí),會(huì)輸出如下結(jié)果

public boolean java.lang.String.equals(java.lang.Object)
public java.lang.String java.lang.String.toString()
public int java.lang.String.hashCode()
public int java.lang.String.compareTo(java.lang.String)
public int java.lang.String.compareTo(java.lang.Object)
public int java.lang.String.indexOf(int)
public int java.lang.String.indexOf(int,int)
public int java.lang.String.indexOf(java.lang.String)
public int java.lang.String.indexOf(java.lang.String,int)
public static java.lang.String java.lang.String.valueOf(int)
public static java.lang.String java.lang.String.valueOf(char)
public static java.lang.String java.lang.String.valueOf(boolean)
public static java.lang.String java.lang.String.valueOf(float)
public static java.lang.String java.lang.String.valueOf(char[],int,int)
public static java.lang.String java.lang.String.valueOf(double)
public static java.lang.String java.lang.String.valueOf(char[])
public static java.lang.String java.lang.String.valueOf(java.lang.Object)
public static java.lang.String java.lang.String.valueOf(long)
public char java.lang.String.charAt(int)
public int java.lang.String.codePointAt(int)
public int java.lang.String.codePointBefore(int)
public int java.lang.String.codePointCount(int,int)
public int java.lang.String.compareToIgnoreCase(java.lang.String)
public java.lang.String java.lang.String.concat(java.lang.String)
public boolean java.lang.String.contains(java.lang.CharSequence)
public boolean java.lang.String.contentEquals(java.lang.CharSequence)
public boolean java.lang.String.contentEquals(java.lang.StringBuffer)
public static java.lang.String java.lang.String.copyValueOf(char[])
public static java.lang.String java.lang.String.copyValueOf(char[],int,int)
public boolean java.lang.String.endsWith(java.lang.String)
public boolean java.lang.String.equalsIgnoreCase(java.lang.String)
public static java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[])
public static java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,java.lang.Object[])
public byte[] java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException
public void java.lang.String.getBytes(int,int,byte[],int)
public byte[] java.lang.String.getBytes()
public byte[] java.lang.String.getBytes(java.nio.charset.Charset)
public void java.lang.String.getChars(int,int,char[],int)
public native java.lang.String java.lang.String.intern()
public boolean java.lang.String.isEmpty()
public int java.lang.String.lastIndexOf(java.lang.String)
public int java.lang.String.lastIndexOf(int,int)
public int java.lang.String.lastIndexOf(int)
public int java.lang.String.lastIndexOf(java.lang.String,int)
public int java.lang.String.length()
public boolean java.lang.String.matches(java.lang.String)
public int java.lang.String.offsetByCodePoints(int,int)
public boolean java.lang.String.regionMatches(boolean,int,java.lang.String,int,int)
public boolean java.lang.String.regionMatches(int,java.lang.String,int,int)
public java.lang.String java.lang.String.replace(java.lang.CharSequence,java.lang.CharSequence)
public java.lang.String java.lang.String.replace(char,char)
public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String)
public java.lang.String java.lang.String.replaceFirst(java.lang.String,java.lang.String)
public java.lang.String[] java.lang.String.split(java.lang.String)
public java.lang.String[] java.lang.String.split(java.lang.String,int)
public boolean java.lang.String.startsWith(java.lang.String)
public boolean java.lang.String.startsWith(java.lang.String,int)
public java.lang.CharSequence java.lang.String.subSequence(int,int)
public java.lang.String java.lang.String.substring(int)
public java.lang.String java.lang.String.substring(int,int)
public char[] java.lang.String.toCharArray()
public java.lang.String java.lang.String.toLowerCase()
public java.lang.String java.lang.String.toLowerCase(java.util.Locale)
public java.lang.String java.lang.String.toUpperCase()
public java.lang.String java.lang.String.toUpperCase(java.util.Locale)
public java.lang.String java.lang.String.trim()
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()

      這樣就列出了java.lang.String類的所有方法名、及其限制符、返回類型及拋出的異常。這個(gè)程序使用Class類forName方法載入指定的類,然后調(diào)用getMethods方法返回指定類的方法列表。java.lang.reflect.Method用來表述某個(gè)類中的單一方法。

      使用java的反射機(jī)制,一般需要遵循三步:

獲得你想操作類的Class對象
通過第一步獲得的Class對象去取得操作類的方法或是屬性名
操作第二步取得的方法或是屬性

     Java運(yùn)行的時(shí)候,某個(gè)類無論生成多少個(gè)對象,他們都會(huì)對應(yīng)同一個(gè)Class對象,它表示正在運(yùn)行程序中的類和接口。如何取得操作類的Class對象,常用的有三種方式:

調(diào)用Class的靜態(tài)方法forName,如上例;

使用類的.class語法,如:Class<?> cls = String.class;
調(diào)用對象的getClass方法,如:String str = "abc";Class<?> cls = str .getClass();

      下面將通過實(shí)例講述如何通過前面所訴的三步來執(zhí)行某對象的某個(gè)方法:

 package com.wanggc.reflection;
 import java.lang.reflect.Method;
 /**
  * Java 反射練習(xí)。
  * 
  * @author Wanggc
  */
 public class ReflectionTest {
   public static void main(String[] args) throws Exception {
     DisPlay disPlay = new DisPlay();
     // 獲得Class
     Class<?> cls = disPlay.getClass();
     // 通過Class獲得DisPlay類的show方法
     Method method = cls.getMethod("show", String.class);
     // 調(diào)用show方法
     method.invoke(disPlay, "Wanggc");
   }
 }
 class DisPlay {
   public void show(String name) {
     System.out.println("Hello :" + name);
   }
 }

      前面說過,Java程序的每個(gè)類都會(huì)有個(gè)Class對象與之對應(yīng)。Java反射的第一步就是獲得這個(gè)Class對象,如代碼14行。當(dāng)然,每個(gè)類的方法也必有一個(gè)Method對象與之對應(yīng)。要通過反射的方式調(diào)用這個(gè)方法,就要首先獲得這個(gè)方法的Method對象,如代碼16行,然后用Method對象反過來調(diào)用這個(gè)方法,如代碼18行。注意16行g(shù)etMethod方法的第一個(gè)參數(shù)是方法名,第二個(gè)是此方法的參數(shù)類型,如果是多個(gè)參數(shù),接著添加參數(shù)就可以了,因?yàn)間etMethod是可變參數(shù)方法。執(zhí)行18行代碼的invoke方法,其實(shí)也就是執(zhí)行show方法,注意invoke的第一個(gè)參數(shù),是DisPlay類的一個(gè)對象,也就是調(diào)用DisPlay類哪個(gè)對象的show方法,第二個(gè)參數(shù)是給show方法傳遞的參數(shù)。類型和個(gè)數(shù)一定要與16行的getMethod方法一直。

      上例講述了如何通過反射調(diào)用某個(gè)類的方法,下面將再通過一個(gè)實(shí)例講述如何通過反射給某個(gè)類的屬性賦值:

 package com.wanggc.reflection;
  import java.lang.reflect.Field;
  /**
  * Java 反射之屬性練習(xí)。
  * 
  * @author Wanggc
  */
 public class ReflectionTest {
   public static void main(String[] args) throws Exception {
     // 建立學(xué)生對象
     Student student = new Student();
     // 為學(xué)生對象賦值
     student.setStuName("Wanggc");
     student.setStuAge();
     // 建立拷貝目標(biāo)對象
     Student destStudent = new Student();
     // 拷貝學(xué)生對象
     copyBean(student, destStudent);
     // 輸出拷貝結(jié)果
     System.out.println(destStudent.getStuName() + ":"
         + destStudent.getStuAge());
   }
   /**
    * 拷貝學(xué)生對象信息。
    * 
    * @param from
    *      拷貝源對象
    * @param dest
    *      拷貝目標(biāo)對象
    * @throws Exception
    *       例外
 */
   private static void copyBean(Object from, Object dest) throws Exception {
     // 取得拷貝源對象的Class對象
     Class<?> fromClass = from.getClass();
     // 取得拷貝源對象的屬性列表
     Field[] fromFields = fromClass.getDeclaredFields();
     // 取得拷貝目標(biāo)對象的Class對象
     Class<?> destClass = dest.getClass();
     Field destField = null;
     for (Field fromField : fromFields) {
       // 取得拷貝源對象的屬性名字
       String name = fromField.getName();
       // 取得拷貝目標(biāo)對象的相同名稱的屬性
       destField = destClass.getDeclaredField(name);
       // 設(shè)置屬性的可訪問性
       fromField.setAccessible(true);
       destField.setAccessible(true);
       // 將拷貝源對象的屬性的值賦給拷貝目標(biāo)對象相應(yīng)的屬性
       destField.set(dest, fromField.get(from));
     }
   }
 }
 /**
  * 學(xué)生類。
  */
 class Student {
   /** 姓名 */
   private String stuName;
   /** 年齡 */
   private int stuAge;
   /**
    * 獲取學(xué)生姓名。
    * 
    * @return 學(xué)生姓名
 */
   public String getStuName() {
     return stuName;
   }
   /**
    * 設(shè)置學(xué)生姓名
    * 
    * @param stuName
    *      學(xué)生姓名
 */
   public void setStuName(String stuName) {
     this.stuName = stuName;
   }
   /**
    * 獲取學(xué)生年齡
    * 
    * @return 學(xué)生年齡
 */
   public int getStuAge() {
     return stuAge;
   }
   /**
    * 設(shè)置學(xué)生年齡
    * 
    * @param stuAge
    *      學(xué)生年齡
 */
   public void setStuAge(int stuAge) {
     this.stuAge = stuAge;
   }
 }

       Java的發(fā)射機(jī)制中類有Class對應(yīng),類的方法有Method對應(yīng),當(dāng)然屬性也有Field與之對應(yīng)。代碼中注釋已經(jīng)做了詳細(xì)的注釋,在此不再贅述。但要注意,F(xiàn)ield提供了get和set方法獲取和設(shè)置屬性的值,但是由于屬性是私有類型,所以需要設(shè)置屬性的可訪問性為true,如代碼50~51行。也可以在為整個(gè)fields設(shè)置可訪問性,在40行下面使用AccessibleObject的靜態(tài)方法setAccessible,如:AccessibleObject.setAccessible(fromFields, true);

      前面講述了如何用Java反射機(jī)制操作一個(gè)類的方法和屬性,下面再通過一個(gè)實(shí)例講述如何在運(yùn)行時(shí)創(chuàng)建類的一個(gè)對象:

package com.wanggc.reflection;
 import java.lang.reflect.Field;
 /**
  * Java 反射之屬性練習(xí)。
  * 
  * @author Wanggc
  */
 public class ReflectionTest {
   public static void main(String[] args) throws Exception {
     // 建立學(xué)生對象
     Student student = new Student();
     // 為學(xué)生對象賦值
     student.setStuName("Wanggc");
     student.setStuAge();
     // 建立拷貝目標(biāo)對象
     Student destStudent = (Student) copyBean(student);
     // 輸出拷貝結(jié)果
     System.out.println(destStudent.getStuName() + ":"
         + destStudent.getStuAge());
   }
   /**
   * 拷貝學(xué)生對象信息。
   * 
   * @param from
   *      拷貝源對象
   * @param dest
   *      拷貝目標(biāo)對象
   * @throws Exception
   *       例外
 */
   private static Object copyBean(Object from) throws Exception {
     // 取得拷貝源對象的Class對象
     Class<?> fromClass = from.getClass();
     // 取得拷貝源對象的屬性列表
     Field[] fromFields = fromClass.getDeclaredFields();
     // 取得拷貝目標(biāo)對象的Class對象
     Object ints = fromClass.newInstance();
     for (Field fromField : fromFields) {
       // 設(shè)置屬性的可訪問性
       fromField.setAccessible(true);
       // 將拷貝源對象的屬性的值賦給拷貝目標(biāo)對象相應(yīng)的屬性
       fromField.set(ints, fromField.get(from));
     }
     return ints;
   }
 }
 /**
 * 學(xué)生類。
 */
 class Student {
   /** 姓名 */
   private String stuName;
   /** 年齡 */
   private int stuAge;
   /**
   * 獲取學(xué)生姓名。
   * 
   * @return 學(xué)生姓名
 */
   public String getStuName() {
     return stuName;
   }
   /**
   * 設(shè)置學(xué)生姓名
   * 
   * @param stuName
   *      學(xué)生姓名
 */
   public void setStuName(String stuName) {
     this.stuName = stuName;
   }
   /**
   * 獲取學(xué)生年齡
   * 
   * @return 學(xué)生年齡
 */
   public int getStuAge() {
     return stuAge;
   }
   /**
   * 設(shè)置學(xué)生年齡
   * 
   * @param stuAge
   *      學(xué)生年齡
 */
   public void setStuAge(int stuAge) {
     this.stuAge = stuAge;
   }
}

      此例和上例運(yùn)行的結(jié)果是相同的。但是copyBean方法返回的對象不再是外面?zhèn)魅氲?,而是由方法?nèi)部產(chǎn)生的,如第40行代碼所示。注意:Class的newInstance方法,只能創(chuàng)建只包含無參數(shù)的構(gòu)造函數(shù)的類,如果某類只有帶參數(shù)的構(gòu)造函數(shù),那么就要使用另外一種方式:fromClass.getDeclaredConstructor(int.class,String.class).newInstance(24,"wanggc");

      至此,Java反射機(jī)制的常用機(jī)能(運(yùn)行時(shí)調(diào)用對象的方法、類屬性的使用、創(chuàng)類類的對象)已經(jīng)介紹完了。

      補(bǔ)充:在獲得類的方法、屬性、構(gòu)造函數(shù)時(shí),會(huì)有g(shù)etXXX和getgetDeclaredXXX兩種對應(yīng)的方法。之間的區(qū)別在于前者返回的是訪問權(quán)限為public的方法和屬性,包括父類中的;但后者返回的是所有訪問權(quán)限的方法和屬性,不包括父類的。

以上內(nèi)容就是給大家介紹的java發(fā)射機(jī)制,希望大家喜歡。

相關(guān)文章

  • Java SpringMVC 異常處理SimpleMappingExceptionResolver類詳解

    Java SpringMVC 異常處理SimpleMappingExceptionResolver類詳解

    這篇文章主要介紹了SpringMVC 異常處理SimpleMappingExceptionResolver類詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • Java中json處理工具JsonPath的使用教程

    Java中json處理工具JsonPath的使用教程

    JsonPath類似于XPath,是一種json數(shù)據(jù)結(jié)構(gòu)節(jié)點(diǎn)定位和導(dǎo)航表達(dá)式語言,這篇文章主要為大家介紹了JsonPath的基本使用,需要的小伙伴可以參考下
    2023-08-08
  • Java FileDescriptor總結(jié)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java FileDescriptor總結(jié)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    FileDescriptor 是“文件描述符”??梢员挥脕肀硎鹃_放文件、開放套接字等。接下來通過本文給大家分享Java FileDescriptor總結(jié),感興趣的朋友一起學(xué)習(xí)吧
    2017-05-05
  • Java 數(shù)組聲明、創(chuàng)建、初始化詳解

    Java 數(shù)組聲明、創(chuàng)建、初始化詳解

    本文主要介紹Java 數(shù)組聲明、創(chuàng)建、初始化的資料,這里整理相關(guān)知識,及簡單實(shí)現(xiàn)代碼,幫助大家學(xué)習(xí),有興趣的小伙伴可以參考下
    2016-09-09
  • springboot controller無效的處理方案

    springboot controller無效的處理方案

    這篇文章主要介紹了springboot controller無效的處理方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 解析JavaSE的繼承和多態(tài)

    解析JavaSE的繼承和多態(tài)

    這篇文章主要為大家詳細(xì)介紹了JavaSE的繼承和多態(tài),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • Java ThreadLocal用法實(shí)例詳解

    Java ThreadLocal用法實(shí)例詳解

    這篇文章主要介紹了Java ThreadLocal用法,結(jié)合實(shí)例形式詳細(xì)分析了ThreadLocal線程局部變量相關(guān)原理、定義與使用方法,需要的朋友可以參考下
    2019-09-09
  • java初學(xué)者如何讓編程學(xué)習(xí)起來更簡單

    java初學(xué)者如何讓編程學(xué)習(xí)起來更簡單

    我們給大家?guī)硪黄P(guān)于java初學(xué)者如何讓編程學(xué)習(xí)起來更簡單的基礎(chǔ)性文章,有需要的朋友們可以學(xué)習(xí)下。
    2020-11-11
  • java實(shí)現(xiàn)賬號登錄時(shí)發(fā)送郵件通知

    java實(shí)現(xiàn)賬號登錄時(shí)發(fā)送郵件通知

    這篇文章主要為大家詳細(xì)介紹了java如何實(shí)現(xiàn)在賬號登錄時(shí)發(fā)送郵件通知的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-09-09
  • 如何查找YUM安裝的JAVA_HOME環(huán)境變量詳解

    如何查找YUM安裝的JAVA_HOME環(huán)境變量詳解

    這篇文章主要給大家介紹了關(guān)于如何查找YUM安裝的JAVA_HOME環(huán)境變量的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10

最新評論

鄢陵县| 徐汇区| 开原市| 沽源县| 马尔康县| 阜南县| 商河县| 瑞安市| 儋州市| 杨浦区| 襄樊市| 永顺县| 杨浦区| 隆化县| 新邵县| 都兰县| 龙陵县| 拜城县| 沁阳市| 文成县| 故城县| 灵武市| 金华市| 江孜县| 商都县| 清远市| 婺源县| 紫阳县| 衡阳县| 皋兰县| 马鞍山市| 永仁县| 于田县| 江西省| 子洲县| 乌恰县| 光山县| 汉川市| 织金县| 敦化市| 隆回县|