程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA編程入門知識 >> Java反射機制的實現詳解

Java反射機制的實現詳解

編輯:JAVA編程入門知識

很多主流框架都使用了反射技術.像ssh框架都采用兩種技術 xml做配置文件+反射技術.

與反射有關的類包.

java.lang.reflect.*;和java.lang.Class;

Java中所有類型(包括基本類型)都對應一個Class對象,這個Class就是java.lang.Class。即每一個類型,在Class中都有一個Class對象跟它對應.Class 沒有公共構造方法。注意不是沒有,是沒有公共的.

如何獲得Class對象
代碼如下:

.針對每一個對象.getCalss(),可以得到對應的Class.
.Class.forName(String),String的寫法:包名.類名.就會創建包名.類名對應的那個對象
注:1.2只適用於引用類型
.對於基本類型:封裝類.TYPE代表了對應的基本類型的Class對象.Integer.TYPE對應的是int的Class對象
注:3只適用於基本類型
.類型,Class。<第4種是通用的.>
上面的4種方法,只有方法2是動態的,只要換一個包就可以了.它具有動態潛質.所以真正意義的想體現動態編程只能使用方法2.

每種類型的Class對象只有一個,即他們的地址只有一個,但是不同類型是不同的.

所以下面的打印結果都為true.
代碼如下:

//對與引用類型
Class c1 = "".getClass();
Class c2 =     Class.forName("java.lang.String");
Class c3 = String.class;
System.out.println(c1 ==c2);//true
//對於基本類型
Class num1 = Integer.TYPE;
Class num2 = int.class;
System.out.println(num1 == num2);//true

反射獲取類中的成員的相關方法

[獲取構造<根據參數類型>](使用時一般用不帶declared的)
代碼如下:

Constructor<T> getConstructor(Class<?>... parameterTypes)
      返回一個 Constructor 對象,它反映此 Class 對象所表示的類的指定公共構造方法。
 Constructor<?>[] getConstructors()
      返回一個包含某些 Constructor 對象的數組,這些對象反映此 Class 對象所表示的類的所有公共構造方法。
 Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
      返回一個 Constructor 對象,該對象反映此 Class 對象所表示的類或接口的指定構造方法。
 Constructor<?>[] getDeclaredConstructors()
      返回 Constructor 對象的一個數組,這些對象反映此 Class 對象表示的類聲明的所有構造方法。

[獲取屬性<根據屬性名>](使用時一般用是帶declared的,因為屬性一般都是私有的)
代碼如下:

Field getField(String name)
      返回一個 Field 對象,它反映此 Class 對象所表示的類或接口的指定公共成員字段。
 Field[] getFields()
      返回一個包含某些 Field 對象的數組,這些對象反映此 Class 對象所表示的類或接口的所有可訪問公共字段。
 Field getDeclaredField(String name)
      返回一個 Field 對象,該對象反映此 Class 對象所表示的類或接口的指定已聲明字段。
 Field[] getDeclaredFields()
      返回 Field 對象的一個數組,這些對象反映此 Class 對象所表示的類或接口所聲明的所有字段。

[獲取方法<方法名加上參數類型>](使用時一般用不帶declared的)
代碼如下:

Method getMethod(String name, Class<?>... parameterTypes)
      返回一個 Method 對象,它反映此 Class 對象所表示的類或接口的指定公共成員方法。
 Method[] getMethods()
      返回一個包含某些 Method 對象的數組,這些對象反映此 Class 對象所表示的類或接口(包括那些由該類或接口聲明的以及從超類和超接口繼承的那些的類或接口)的公共 member 方法。
 Method getDeclaredMethod(String name, Class<?>... parameterTypes)
      返回一個 Method 對象,該對象反映此 Class 對象所表示的類或接口的指定已聲明方法。
 Method[] getDeclaredMethods()
      返回 Method 對象的一個數組,這些對象反映此 Class 對象表示的類或接口聲明的所有方法,包括公共、保護、默認(包)訪問和私有方法,但不包括繼承的方法。
 T newInstance()
      創建此 Class 對象所表示的類的一個新實例。 <new Instance()可以動態的創建對象>
 String toString()
      將對象轉換為字符串。

注意:

new Instance()調用的是無參構造,如果該類沒有無參構造方法,則newInstance()會產生異常.

有declared的方法是支持私有,但是不支持繼承,無declared的方法支持繼承,不支持私有,且只能取出public的東西.

因此取屬性的時候一般來說是帶declared的,因為屬性一般都是私有的,取方法時一般是不帶declared的,取構造時一般也是不帶declared的.

實例模擬反射獲取類中的相關屬性和方法

利用反射對屬性賦值

Field中的方法

 Object get(Object obj)

  返回指定對象上此 Field 表示的字段的值。

      Field f = c.getXXField(屬性名);

      值 = f.get(對象);

 void set(Object obj, Object value)

  將指定對象變量上此 Field 對象表示的字段設置為指定的新值。

  f.set(對象,值);

 Class<?> getType()

  返回一個 Class 對象,它標識了此 Field 對象所表示字段的聲明類型。

      用於獲取屬性的類型(返回Class對象).
代碼如下:

Class c = Student.class;
    Object obj  = c.newInstance();            //創建Student類的對象
    Field f = c.getDeclaredField("name");        //獲取name屬性
    f.setAccessible(true);                    //設置私有可以訪問.
    f.set(obj, "zhangsan");
    System.out.println(f.get(obj));             //獲取obj的name屬性的值.

利用反射調用構造

對於構造真正調用是在調用newInstance()方法時.
代碼如下:

Class c = Class.forName("com.clazz.reflect.Student");
    Constructor con = c.getConstructor();         //沒有執行構造,
    Object cObj = c.getConstructor().newInstance();//調用無參的構造方法
    Constructor conAll = c.getConstructor(int.class,String.class,int.class);
    Object caobj = conAll.newInstance(1001,"zjamgs",234235);//調用含參的構造方法.
    System.out.println(caobj);                  //打印輸出

利用反射調用方法

對象.方法名(值1,2,3);

Method m = c.getMethoed(方法名,參數類型...);

m.invoke(對象,方法調用的參數 )如果底層方法所需的形參數為 0,則所提供的 args 數組長度可以為 0 或 null。
代碼如下:

Class c = Class.forName("com.clazz.reflect.Student");
    Object obj = c.newInstance();    //創建Sutdent對象.
    Method msetName = c.getMethod("setName", String.class);//obj無須轉換類型
    msetName.invoke(obj, "zhangsan");//調用方法setName, 並傳參.
    Method msetId = c.getMethod("setId", int.class);
    msetId.invoke(obj, 409090202);
    System.out.println(obj);

反射應用實例

實體類
代碼如下:

package org.dennisit.reflect.entity;
import java.io.Serializable;
/**
 *
 *  User.java   
 *
 *  @version : 1.1
 * 
 *  @author  : 蘇若年    <a href="mailto:[email protected]">發送郵件</a>
 *   
 *  @since     : 1.0        創建
反射測試類
代碼如下:

package org.dennisit.reflect.main;
import java.lang.reflect.Field;
/**
 *
 *  ReflectEx.java   
 *
 *  @version : 1.1
 * 
 *  @author  : 蘇若年    <a href="mailto:[email protected]">發送郵件</a>
 *   
 *  @since     : 1.0        創建
運行效果
代碼如下:

zhangsan
name=dennisit,age=23

編寫一個反射動態實例化類的例子
代碼如下:

package org.dennisit.reflect.main;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
/**
 *
 *  DynamicReflect.java   
 *
 *  @version : 1.1
 * 
 *  @author  : 蘇若年    <a href="mailto:[email protected]">發送郵件</a>
 *   
 *  @since     : 1.0        創建
接下來我們測試我們編寫的動態反射實例化例子

實體類
代碼如下:

package org.dennisit.reflect.entity;
import java.io.Serializable;
/**
 *
 *  User.java   
 *
 *  @version : 1.1
 * 
 *  @author  : 蘇若年    <a href="mailto:[email protected]">發送郵件</a>
 *   
 *  @since     : 1.0        創建
主測試類
代碼如下:

package org.dennisit.reflect.main;
import java.util.HashMap;
import java.util.Map;
import org.dennisit.reflect.entity.User;
/**
 *
 *  ReflectEx.java   
 *
 *  @version : 1.1
 * 
 *  @author  : 蘇若年    <a href="mailto:[email protected]">發送郵件</a>
 *   
 *  @since     : 1.0        創建
程序運行結果
代碼如下:

dennisit,22,[email protected]

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved