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

Java反射機制詳解

 更新時間:2015年12月09日 14:30:13   作者:西電一枝花  
這篇文章主要介紹了Java反射機制,首先簡單介紹了反射機制的預(yù)備知識,進一步分析了Java反射機制的原理、實現(xiàn)技巧與應(yīng)用方法,需要的朋友可以參考下

本文較為詳細(xì)的分析了Java反射機制。分享給大家供大家參考,具體如下:

一、預(yù)先需要掌握的知識(java虛擬機)

java虛擬機的方法區(qū):

java虛擬機有一個運行時數(shù)據(jù)區(qū),這個數(shù)據(jù)區(qū)又被分為方法區(qū),堆區(qū)和棧區(qū),我們這里需要了解的主要是方法區(qū)。方法區(qū)的主要作用是存儲被裝載的類 的類型信息,當(dāng)java虛擬機裝載某個類型的時候,需要類裝載器定位相應(yīng)的class文件,然后將其讀入到j(luò)ava虛擬機中,緊接著虛擬機提取class 中的類型信息,將這些信息存儲到方法區(qū)中。這些信息主要包括:

1、這個類型的全限定名

2、這個類型的直接超類的全限定名

3、這個類型是類類型還是接口類型

4、這個類型的訪問修飾符

5、任何直接超接口的全限定名的有序列表

6、該類型的常量池

7、字段信息

8、方法信息

9、除了常量以外的所有類變量

10、一個到class類的引用

等等(讀者可以參考《深入java虛擬機》這本書的敘述)

Class類:

Class類是一個非常重要的java基礎(chǔ)類,每當(dāng)裝載一個新的類型的時候,java虛擬機都會在java堆中創(chuàng)建一個對應(yīng)于新類型的Class實例,該實例就代表此類型,通過該Class實例我們就可以訪問該類型的基本信息。上面說到在方法區(qū)中會存儲某個被裝載類的類型信息,我們就可以通過 Class實例來訪問這些信息。比如,對于上面說到的信息Class中都有對應(yīng)的方法,如下:

1、getName();這個類型的全限定名

2、getSuperClass();這個類型的直接超類的全限定名

3、isInterface();這個類型是類類型還是接口類型

4、getTypeParamters();這個類型的訪問修飾符

5、getInterfaces();任何直接超接口的全限定名的有序列表

6、getFields();字段信息

7、getMethods();方法信息

等等(讀者可以自己參看jdk幫助文檔,得到更多的信息)

二、java反射詳解

反射的概念:所謂的反射就是java語言在運行時擁有一項自觀的能力,反射使您的程序代碼能夠得到裝載到JVM中的類的內(nèi)部信息,允許您執(zhí)行程序時才得到需要類的內(nèi)部信息,而不是在編寫代碼的時候就必須要知道所需類的內(nèi)部信息,這使反射成為構(gòu)建靈活的應(yīng)用的主要工具。

反射的常用類和函數(shù):Java反射機制的實現(xiàn)要借助于4個類:Class,Constructor,F(xiàn)ield,Method;其中class代 表的是類對象,Constructor-類的構(gòu)造器對象,F(xiàn)ield-類的屬性對象,Method-類的方法對象,通過這四個對象我們可以粗略的看到一個類的各個組成部分。其中最核心的就是Class類,它是實現(xiàn)反射的基礎(chǔ),它包含的方法我們在第一部分已經(jīng)進行了基本的闡述。應(yīng)用反射時我們最關(guān)心的一般是一個類的構(gòu)造器、屬性和方法,下面我們主要介紹Class類中針對這三個元素的方法:

1、得到構(gòu)造器的方法

Constructor getConstructor(Class[] params) -- 獲得使用特殊的參數(shù)類型的公共構(gòu)造函數(shù),

Constructor[] getConstructors() -- 獲得類的所有公共構(gòu)造函數(shù)

Constructor getDeclaredConstructor(Class[] params) -- 獲得使用特定參數(shù)類型的構(gòu)造函數(shù)(與接入級別無關(guān))

Constructor[] getDeclaredConstructors() -- 獲得類的所有構(gòu)造函數(shù)(與接入級別無關(guān))

2、獲得字段信息的方法

Field getField(String name) -- 獲得命名的公共字段

Field[] getFields() -- 獲得類的所有公共字段

Field getDeclaredField(String name) -- 獲得類聲明的命名的字段

Field[] getDeclaredFields() -- 獲得類聲明的所有字段
3、獲得方法信息的方法

Method getMethod(String name, Class[] params) -- 使用特定的參數(shù)類型,獲得命名的公共方法

Method[] getMethods() -- 獲得類的所有公共方法

Method getDeclaredMethod(String name, Class[] params) -- 使用特寫的參數(shù)類型,獲得類聲明的命名的方法

Method[] getDeclaredMethods() -- 獲得類聲明的所有方法

應(yīng)用反射的基本步驟:

1、獲得你想操作的類的Class對象;

方法一:Classc=Class.forName("java.lang.String") //這種方式獲得類的Class對象需要 包名.類名

方法二:對于基本數(shù)據(jù)類型可以用形如Class c=int.class或Class c=Integer.TYPE的語句

方法三:Class c=MyClass.class

2、調(diào)用Class中的方法得到你想得到的信息集合,如調(diào)用getDeclaredFields()方法得到類的所有屬性;

3、處理第2步中得到的信息,然后進行你想做的實際操作。

反射實例:

下面我將針對類的構(gòu)造器、屬性和方法分別舉三個例子,向大家演示一下反射的應(yīng)用過程。

1、構(gòu)造器

步驟為:通過反射機制得到某個類的構(gòu)造器,然后調(diào)用該構(gòu)造器創(chuàng)建該類的一個實例

import java.lang.reflect.*; 
public class ConstructorDemo{ 
  public ConstructorDemo(){ } 
  public ConstructorDemo(int a, int b){ 
   System.out.println("a="+a+"b="+b); 
  } 
  public static void main(String args[]){ 
    try { 
      Class cls =Class.forName("包名.ConstructorDemo"); 
      Class partypes[] =new Class[2]; partypes[0] = Integer.TYPE;  
      partypes[1] =Integer.TYPE; 
      Constructor ct=cls.getConstructor(partypes); 
      Object arglist[] =new Object[2]; 
      arglist[0] = newInteger(37); 
      arglist[1] = newInteger(47); 
      Object retobj = ct.newInstance(arglist); 
     } catch (Throwable e) {
      System.err.println(e);} 
     } 
  } 

2、屬性

步驟為:通過反射機制得到某個類的某個屬性,然后改變對應(yīng)于這個類的某個實例的該屬性值

import java.lang.reflect.*; 
public class FieldDemo1{ 
 public double d; 
 public static void main(String args[]){ 
 try { 
  Class cls = Class.forName("FieldDemo1"); 
  Field fld = cls.getField("d"); 
  FieldDemo1 fobj = new FieldDemo1(); 
  System.out.println("d = " + fobj.d); 
  fld.setDouble(fobj, 12.34); 
  System.out.println("d = " + fobj.d); 
 } catch (Throwable e){ 
  System.err.println(e); } 
 } 
} 

3、方法

步驟為:通過反射機制得到某個類的某個方法,然后調(diào)用對應(yīng)于這個類的某個實例的該方法

//通過使用方法的名字調(diào)用方法 
import java.lang.reflect.*; 
public class MethodDemo1{ 
 public int add(int a, int b){ 
 return a + b; 
 } 
 public static void main(String args[]){ 
  try { 
   Class cls =Class.forName("MethodDemo1"); 
   Class partypes[] = new Class[2]; 
   partypes[0] = Integer.TYPE; 
   partypes[1] = Integer.TYPE; 
   Method meth = cls.getMethod("add",partypes); 
   MethodDemo1 methobj = new MethodDemo1(); 
   Object arglist[] = new Object[2]; 
   arglist[0] = new Integer(37); 
   arglist[1] = new Integer(47); 
   Object retobj= meth.invoke(methobj, arglist); 
   Integer retval = (Integer)retobj; 
   System.out.println(retval.intValue()); 
  } catch (Throwable e) { 
   System.err.println(e); 
  } 
 } 
}

三、java反射的應(yīng)用(Hibernate)

我們在第二部分中對java反射進行了比較系統(tǒng)的闡述,也舉了幾個簡單的實例,下面我們就來討論一下java反射的具體應(yīng)用。前面我們已經(jīng)知 道,Java反射機制提供了一種動態(tài)鏈接程序組件的多功能方法,它允許程序創(chuàng)建和控制任何類的對象(根據(jù)安全性限制)之前,無需提前硬編碼目標(biāo)類。這些特 性使得反射特別適用于創(chuàng)建以非常普通的方式與對象協(xié)作的庫。例如,反射經(jīng)常在持續(xù)存儲對象為數(shù)據(jù)庫、XML或其它外部格式的框架中使用。下面我們就已 Hibernate框架為例像大家闡述一下反射的重要意義。

Hibernate是一個屏蔽了JDBC,實現(xiàn)了ORM的java框架,利用該框架我們可以拋棄掉繁瑣的sql語句而是利用Hibernate中 Session類的save()方法直接將某個類的對象存到數(shù)據(jù)庫中,也就是所涉及到sql語句的那些代碼Hibernate幫我們做了。這時候就出現(xiàn)了 一個問題,Hibernate怎樣知道他要存的某個對象都有什么屬性呢?這些屬性都是什么類型呢?如此,它在向數(shù)據(jù)庫中存儲該對象屬性時的sql語句該怎么構(gòu)造呢?解決這個問題的利器就是我們的java反射!

下面我們以一個例子來進行闡述,比如我們定義了一個User類,這個User類中有20個屬性和這些屬性的get和set方法,相應(yīng)的在數(shù)據(jù)庫中 有一個User表,這個User表中對應(yīng)著20個字段。假設(shè)我們從User表中提取了一條記錄,現(xiàn)在需要將這條記錄的20個字段的內(nèi)容分別賦給一個 User對象myUser的20個屬性,而Hibernate框架在編譯的時候并不知道這個User類,他無法直接調(diào)用myUser.getXXX或者 myUser.setXXX方法,此時就用到了反射,具體處理過程如下:

1、根據(jù)查詢條件構(gòu)造PreparedStament語句,該語句返回20個字段的值;

2、Hibernate通過讀取配置文件得到User類的屬性列表list(是一個String數(shù)組)以及這些屬性的類型;

3、創(chuàng)建myUser所屬類的Class對象c;c=myUser.getClass();

4、構(gòu)造一個for循環(huán),循環(huán)的次數(shù)為list列表的長度;

4.1、讀取list[i]的值,然后構(gòu)造對應(yīng)該屬性的set方法;

4.2、判斷l(xiāng)ist[i]的類型XXX,調(diào)用PreparedStament語句中的getXXX(i),進而得到i出字段的值;

4.3、將4.2中得到的值作為4.1中得到的set方法的參數(shù),這樣就完成了一個字段像一個屬性的賦值,如此循環(huán)即可;

看到了吧,這就是反射的功勞,如果沒有反射很難想象如果完成同樣的功能會有多么難!但是反射也有缺點,比如性能比較低、安全性比較復(fù)雜等,這里就不在討論這些東西,感興趣的讀者可以在網(wǎng)上找到答案,有很多的!

希望本文所述對大家Java程序設(shè)計有所幫助。

相關(guān)文章

  • Java歸并排序算法代碼實現(xiàn)

    Java歸并排序算法代碼實現(xiàn)

    歸并(Merge)排序法是將兩個(或兩個以上)有序表合并成一個新的有序表,即把待排序序列分為若干個子序列,每個子序列是有序的,下面這篇文章主要給大家介紹了關(guān)于Java歸并排序算法的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • Java多線程的用法詳細(xì)介紹

    Java多線程的用法詳細(xì)介紹

    這篇文章主要介紹了Java多線程的用法詳細(xì)介紹的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • Java多線程 自定義線程池詳情

    Java多線程 自定義線程池詳情

    這篇文章主要介紹了Java多線程 自定義線程池,文章主要是學(xué)習(xí)代碼,沒有過多解析,需要的朋友可以參考一下文章的具體內(nèi)容
    2021-10-10
  • Intellij Idea 多模塊Maven工程中模塊之間無法相互引用問題

    Intellij Idea 多模塊Maven工程中模塊之間無法相互引用問題

    這篇文章主要介紹了Intellij Idea 多模塊Maven工程中模塊之間無法相互引用問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • SpringBoot增強Controller方法@ControllerAdvice注解的使用詳解

    SpringBoot增強Controller方法@ControllerAdvice注解的使用詳解

    這篇文章主要介紹了SpringBoot增強Controller方法@ControllerAdvice注解的使用詳解,@ControllerAdvice,是Spring3.2提供的新注解,它是一個Controller增強器,可對controller進行增強處理,需要的朋友可以參考下
    2023-10-10
  • Java數(shù)據(jù)結(jié)構(gòu)順序表用法詳解

    Java數(shù)據(jù)結(jié)構(gòu)順序表用法詳解

    順序表是計算機內(nèi)存中以數(shù)組的形式保存的線性表,線性表的順序存儲是指用一組地址連續(xù)的存儲單元依次存儲線性表中的各個元素、使得線性表中在邏輯結(jié)構(gòu)上相鄰的數(shù)據(jù)元素存儲在相鄰的物理存儲單元中,即通過數(shù)據(jù)元素物理存儲的相鄰關(guān)系來反映數(shù)據(jù)元素之間邏輯上的相鄰關(guān)系
    2021-10-10
  • SpringMVC實現(xiàn)Validation校驗過程詳解

    SpringMVC實現(xiàn)Validation校驗過程詳解

    這篇文章主要介紹了SpringMVC實現(xiàn)Validation校驗過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • java中設(shè)計模式(多例)的實例詳解

    java中設(shè)計模式(多例)的實例詳解

    這篇文章主要介紹了java中設(shè)計模式(多例)的實例詳解的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • Java抽象類與接口區(qū)別詳解

    Java抽象類與接口區(qū)別詳解

    這篇文章主要介紹了Java抽象類與接口區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03
  • java?stream實現(xiàn)分組BigDecimal求和以及自定義分組求和

    java?stream實現(xiàn)分組BigDecimal求和以及自定義分組求和

    這篇文章主要給大家介紹了關(guān)于java?stream實現(xiàn)分組BigDecimal求和以及自定義分組求和的相關(guān)資料,Stream是Java8的一大亮點,是對容器對象功能的增強,它專注于對容器對象進行各種非常便利、高效的聚合操作或者大批量數(shù)據(jù)操作,需要的朋友可以參考下
    2023-12-12

最新評論