C語言中文網 目錄
首頁 > Java教程 > Java反射機制 閱讀:1,168

Java反射在類中的應用:通過反射訪問構造函數(方法)

為了能夠動態獲取對象構造方法的信息,首先需要通過下列方法之一創建一個 Constructor 類型的對象或者數組。
  • getConstructors()
  • getConstructor(Class<?>…parameterTypes)
  • getDeclaredConstructors()
  • getDeclaredConstructor(Class<?>...parameterTypes)

如果是訪問指定的構造方法,需要根據該構造方法的入口參數的類型來訪問。例如,訪問一個入口參數類型依次為 int 和 String 類型的構造方法,下面的兩種方式均可以實現。
objectClass.getDeclaredConstructor(int.class,String.class);
objectClass.getDeclaredConstructor(new Class[]{int.class,String.class});

創建的每個 Constructor 對象表示一個構造方法,然后利用 Constructor 對象的方法操作構造方法。Constructor 類的常用方法如表 1 所示。
表1 Constructor類的常用方法
方法名稱 說明
isVarArgs() 查看該構造方法是否允許帶可變數量的參數,如果允許,返回 true,否則返回
false
getParameterTypes() 按照聲明順序以 Class 數組的形式獲取該構造方法各個參數的類型
getExceptionTypes() 以 Class 數組的形式獲取該構造方法可能拋出的異常類型
newInstance(Object … initargs) 通過該構造方法利用指定參數創建一個該類型的對象,如果未設置參數則表示
采用默認無參的構造方法
setAccessiable(boolean flag) 如果該構造方法的權限為 private,默認為不允許通過反射利用 netlnstance()
方法創建對象。如果先執行該方法,并將入口參數設置為 true,則允許創建對
getModifiers() 獲得可以解析出該構造方法所采用修飾符的整數

通過 java.lang.reflect.Modifier 類可以解析出 getMocMers() 方法的返回值所表示的修飾符信息。在該類中提供了一系列用來解析的靜態方法,既可以查看是否被指定的修飾符修飾,還可以字符串的形式獲得所有修飾符。表 2 列出了 Modifier 類的常用靜態方法。

表2 Modifier類的常用方法
靜態方法名稱 說明
isStatic(int mod) 如果使用 static 修飾符修飾則返回 true,否則返回 false
isPublic(int mod) 如果使用 public 修飾符修飾則返回 true,否則返回 false
isProtected(int mod) 如果使用 protected 修飾符修飾則返回 true,否則返回 false
isPrivate(int mod) 如果使用 private 修飾符修飾則返回 true,否則返回 false
isFinal(int mod) 如果使用 final 修飾符修飾則返回 true,否則返回 false
toString(int mod) 以字符串形式返回所有修飾符

例如,下列代碼判斷對象 con 所代表的構造方法是否被 public 修飾,以及以字符串形式獲取該構造方法的所有修飾符。
int modifiers=con.getModifiers();    //獲取構造方法的修飾符整數
boolean isPubiic=Modifier.isPublic(modifiers);    //判斷修飾符整數是否為
public string ailModifSers=Modifier.toString(modifiers);

例 1

下面通過一個案例來演示如何調用 Constructor 類的方法獲取構造方法的信息。

(1) 首先創建一個 Book 類表示圖書信息。在該類中聲明一個 String 型變量表示圖書名稱,兩個 int 型變量分別表示圖書編號和價格,并提供 3 個構造方法。

Book 類的最終代碼如下:
public class Book
{
    String name;    //圖書名稱
    int id,price;    //圖書編號和價格
    //空的構造方法
    private Book(){}
    //帶兩個參數的構造方法
    protected Book(String _name,int _id)
    {
        this.name=_name;
        this.id=_id;
    }
    //帶可變參數的構造方法
    public Book(String...strings)throws NumberFormatException
    {
        if(0<strings.length)
            id=Integer.valueOf(strings[0]);
        if(1<strings.length)
            price=Integer.valueOf(strings[1]);
    }
    //輸出圖書信息
    public void print()
    {
        System.out.println("name="+name);
        System.out.println("id="+id);
        System.out.println("price="+price);
    }
}

(2) 編寫測試類 Test01,在該類的 main() 方法中通過反射訪問 Book 類中的所有構造方法,并將該構造方法是否帶可變類型參數、入口參數類型和可能拋出的異常類型信息輸出到控制臺。

Test01 類的代碼如下:
import java.lang.reflect.Constructor;
public class Test01
{
    public static void main(String[] args)
    {
        //獲取動態類Book
        Class book=Book.class;
        //獲取Book類的所有構造方法
        Constructor[] declaredContructors=book.getDeclaredConstructors();
        //遍歷所有構造方法
        for(int i=0;i<declaredContructors.length;i++)
        {
            Constructor con=declaredContructors[i];
            //判斷構造方法的參數是否可變
            System.out.println("查看是否允許帶可變數量的參數:"+con.isVarArgs());
            System.out.println("該構造方法的入口參數類型依次為:");
            //獲取所有參數類型
            Class[] parameterTypes=con.getParameterTypes();
            for(int j=0;j<parameterTypes.length;j++)
            {
                System.out.println(" "+parameterTypes[j]);
            }
            System.out.println("該構造方法可能拋出的異常類型為:");
            //獲取所有可能拋出的異常類型
            Class[] exceptionTypes=con.getExceptionTypes();
            for(int j=0;j<exceptionTypes.length;j++)
            {
                System.out.println(" "+parameterTypes[j]);
            }
            //創建一個未實例化的Book類實例
            Book book1=null;
            while(book1==null)
            {
                try
                {    //如果該成員變量的訪問權限為private,則拋出異常
                    if(i==1)
                    {
                        //通過執行帶兩個參數的構造方法實例化book1
                        book1=(Book)con.newInstance("Java 教程",10);
                    }
                    else if(i==2)
                    {
                        //通過執行默認構造方法實例化book1
                        book1=(Book)con.newInstance();
                    }
                    else
                    {
                        //通過執行可變數量參數的構造方法實例化book1
                        Object[] parameters=new Object[]{new String[]{"100","200"}};
                        book1=(Book)con.newInstance(parameters);
                    }
                }
                catch(Exception e)
                {
                    System.out.println("在創建對象時拋出異常,下面執行 setAccessible() 方法");
                    con.setAccessible(true);    //設置允許訪問 private 成員
                }
            }
            book1.print();
            System.out.println("=============================\n");
        }
    }
}

(3) 運行測試類 Test01,當通過反射訪問默認構造方法 Book() 時,將看到如下所示的輸出。
查看是否允許帶可變數量的參數:false
該構造方法的入口參數類型依次為:
該構造方法可能拋出的異常類型為:
在創建對象時拋出異常,下面執行setAccessible()方法
name=null
id=0
price=0
=============================

當通過反射訪問兩個參數的構造方法 Book(String_name,int_id) 時,將看到如下所示的輸出。
查看是否允許帶可變數量的參數:false
該構造方法的入口參數類型依次為:
class java.lang.String
int
該構造方法可能拋出的異常類型為:
在創建對象時拋出異常,下面執行setAccessible()方法
name=null
id=0
price=0
=============================

當通過反射訪問可變參數數量的構造方法 Book(String...strings) 時,將看到如下所示的輸出。
查看是否允許帶可變數量的參數:true
該構造方法的入口參數類型依次為:
class java.lang.String;
該構造方法可能拋出的異常類型為:
class java.lang.String;
在創建對象時拋出異常,下面執行setAccessible()方法
name=null
id=0
price=0
=============================

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo