跳到主要內容

Java Reflection(反射機制)之一

Java Reflection -1 (反射機制)

Java Reflection最著名例子就是Spring,它帶來XML和Reflection的結合,可以讓開發者可以動態配置資訊、生成物件或是操過物件,何種情況需要使用Java 反射? 讓我們想一想,有些情況是否需要外部的資訊來決定程式的邏輯或是資料,或是有些情況系統之間希望保持低偶合關係。這些你都可以使用反射機制來完成,例如系統可以提供plugin的功能,來擴充系統的檢查功能,這時候可以利用反射不失為一個辦法。

Java Bean 反射範例

POJO物件 以Employee為例一個反射的對象,我們會介紹利用JAVA的反射設機制,如何將類別解析與載入內容。在一個class類架構會有: Method方法、Field屬性、Constructor建構子,如何分別解析並載入內容,是本章節的重點。

/*
*  name: 員工類別的POJO
*/
public class Employee{

    public  Employee(String id){
        this.id = id ;
    }

    public  Employee(String id, String cname){
        this.id = id ;
        this.cname = cname ;
    }

    private String id ; 
    private String cname ; 
    private String sex ;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getCname() {
        return cname;
    }
    public void setCname(String cname) {
        this.cname = cname;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    } 

    @Override
    public String toString() {
         return "id:"+id+",cname:"+cname+", sex:"+sex ; 
    }
}

類別反射與載入

類別反射是當我需要使用的類別時,我才做載入的動作,也稱為動態載入。如果是程式啟動時就載入,缺點比較耗資源。所以動態載入會讓系統資源更有效的運用。首先 java.lang.Class 物件代表 在運行時所載入的類別或介面實例,使用Class類別可以取得類別的資訊或是生成實例。

  • Class類別API
函式 說明
public static Class forName(String className) 類別的對象
public T newInstance() 返回一個生成實例
public class TestClass01 {
    public static void main(String[] args) {

        Class<?> c1 = Employee.class ; 
        System.out.println("c1-->"+c1);

        try {
            Class<?> c2 = Class.forName("com.tw.refleciton.Employee") ;
            System.out.println("c2-->"+c2);
            System.out.println("c2-->"+c2.getName());
            System.out.println("c2-->"+c2.getSimpleName());
            System.out.println("c2-->"+c2.getEnclosingClass());
        } catch (ClassNotFoundException e) {

            e.printStackTrace();
        }
    }
}
public class TestClass02 {
    public static void main(String[] args) {

        try {
            Class<?> c3 = Class.forName("com.tw.refleciton.Employee") ;
            Object o1 = c3.newInstance() ; 
            System.out.println("c3-->"+c3);
            System.out.println("o1-->"+o1);

        } catch (ClassNotFoundException e) {

            e.printStackTrace();
        } catch (InstantiationException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        }
    }
}

建構子載入

  • Constructor类API
函式 說明
Constructor[] getConstructors() 取得該類別的建構子陣列
Constructor getConstructor(Class… parameterTypes) 符合參數類別,取得建構子對象
T newInstance(Object… initargs) 將內容值設定建構子並生成實例
/*
* name: 取得建構子資訊
*/
public class TestClass03 {
    public static void main(String[] args) {

        try {
            Class<?> c3 = Class.forName("com.tw.refleciton.Employee") ;
            Constructor<?>[] cs = c3.getConstructors();
            for(Constructor<?> c : cs ){
                System.out.print(c.getName()+", parameter size:"+c.getParameterTypes().length);
                Class<?>[] parameters = c.getParameterTypes();
                int i=1 ; 
                if(parameters!=null && parameters.length>0){
                    for(Class<?> p : parameters){
                        System.out.print(",parameter"+i+":"+p.getName()+" , ");
                        i++; 
                    }
                }
                System.out.println();

            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
結果
com.tw.refleciton.Employee, parameter size:2,parameter1:java.lang.String , ,parameter2:java.lang.String ,
com.tw.refleciton.Employee, parameter size:1,parameter1:java.lang.String ,
/*
 * name:有參數化建構子
 * 利用建構子參數化宣告,必須有參數初始化建構子
 */
public class TestClass04 {
    public static void main(String[] args) {
        try {
            Class<?> c = Class.forName("com.tw.refleciton.Employee") ;
            Constructor<?> cs = c.getConstructor(String.class, String.class);
            Object o = cs.newInstance("0001", "丁大幅") ; 
            System.out.println(o.toString());

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // MARK Auto-generated catch block
            e.printStackTrace();
        } 
    }
}
結果
id:0001,cname:丁大幅, sex:nul

屬性載入

  • 屬性常用的API
函式 說明
Field[] getDeclaredFields() 取得所有屬性
Field getDeclaredField(String name) 取得指定的屬性
void set(Object obj, Object value) 設定屬性的新內容值
Object get(Object obj) 取得屬性的內容值
void setAccessible(boolean flag) 設定該屬性是否可以訪問true: 可以訪問、false : 不可以訪問
boolean isAccessible() 該屬性是否可以訪問true: 可以訪問、false : 不可以訪問


/**
 * name:解析field的欄位名稱
 */
public class TestClass05 {

    public static void main(String[] args) {

        try {
            Class<?> c5 = Class.forName("com.tw.refleciton.Employee") ;
            Field[] fs = c5.getDeclaredFields() ; 
            if(fs.length>0){
                for(Field f: fs){
                    System.out.println("field:"+f.getName());
                }

            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
結果
name:sex,value –>> 男id:0002,cname:王大明, sex:男

參考

  1. https://github.com/JustinSDK/JavaSE6Tutorial/blob/master/docs/CH16.md
  2. Java反射机制连载(1)– JavaBean
  3. Java反射机制连载(2)– Class类
  4. Java反射机制连载(3)– Constructor类
  5. Java反射机制连载(4)– Field类
  6. Java反射机制连载(5)– Method类
  7. Java反射机制连载(6)– PropertyDescriptor类
  8. Java反射机制连载(7)– 使用反射实现的ORM持久层框架 attachment
  9. Java反射机制连载(7)– 使用反射实现的ORM持久层框架 attachment
  10. Java反射机制连载(9)– 自定义持久层框架之JdbcOperations接口

留言

這個網誌中的熱門文章

JavaBean 和POJO

前言 今天介紹JavaBean和POJO的不同,這兩個名詞在JAVA文章常常被拿來使用以及討論。在JDK1.1時候釋出才有的一個標準架構,很多時候常常被搞混,所以我們特別開闢一章來加以討論。POJO規範在企業級應用已經廣大的被使用的規範。 解釋 POJO : 全名為Plain-old-Java-object,只需要繼承Object就可以,沒有特定規定,只要建立的類別有setter/getter方法都可以稱為POJO JavaBean: JavaBean通常用來封裝多個物件成為單獨物件使用,規範比較嚴格,規則如下 規則 說明 1 需要實作序列(Serializable/Externalizable) 2 不能有參數的建構子( no-arg constructor) 3 需要有公用setter/getter 4 屬性必須要私人(private) 5 屬於特定POJO規則 比較 所有的JavaBean都為POJO,但是所有的POJO不一定為JavaBean 都可以當作重複元件 都必須序列化 特性都為可用性、易用性和持久化使用 - 應用 由圖我們可以知道POJO在應用程式中,主要用來存取資料庫資料達到持久化的目的,並提供給商業邏輯流程處理使用。這種POJO的架構提供程式人員開發時的可以很有規則將資料封裝並加以使用。 範例1. JavaBean(以員工為實例) JavaBean建立員工物件,可以發現Employee物件建構子沒有任何參數,屬性為私有化並setter/getter的命名方式。 //實作序列化 public class Employee implements java.io.Serializable{ private int id; private String name; //無參數建構子 public Employee(){} //以下實作setter/getter public void setId(int id){this.id=id;} public int getId(){return id;} public void setName(String ...

Python AI-問題集

Python AI-問題集 問題集 Jupyter Notebook執行ipywidgets會出現kernel死掉的錯誤發生(The kernel appears to have died) 解決方法 (1) 根據log檔來判斷問題: 例如:log訊息出現OMP: Error #15: Initializing libiomp5.dylib, but found libiomp5.dylib already initialized. (2) 根據問題關鍵字找出問題所在: 利用google查詢所遭遇到的問題,例如我把上面的問題上google查詢可以找到這篇的解法 https://blog.csdn.net/bingjianIT/article/details/86182096 (3)實作解法: 我實作下面解法後,就可以順利執行手寫辨識的程式. //在Python宣告時加入 import os os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" 參考 https://blog.csdn.net/bingjianIT/article/details/86182096

淺談機器學習原理-Nonlinear Transform

Nonlinear Transform 淺談機器學習原理-Nonlinear Transform Nonlinear Transform *通用能力 gerneralization : 就是將訓練好的模型,放到正式環境可以正常的運作,通常Linear Model的gerneralization會比較好,因為線性模型解決的問題比較單純。缺點是應用侷限比較大。 參考Chih-Chung Chang老師的範例:縣性與非線性分類範例 https://www.csie.ntu.edu.tw/~cjlin/libsvm/ 非線性問題 當如果今天假設要圈出裡面小圈圈的資料,我們就無法使用線性的模型,我們可以用非線性解像圈圈的方程式 s i g n ( − x 1 2 − x 2 2 + r ) sign(-x1^2-x2^2+r) s i g n ( − x 1 2 − x 2 2 + r ) 來解決,在演算法我們利用reduce來將不會的問題透過已知的問題來解決,所以在這個問題 我們將圈圈的方程式(非線性模型)reduce成線性模型來解決。 Reduce 方法論 我們調整圓形的方程式改為 z 0 z_0 z 0 ​ , z 1 z_1 z 1 ​ , z 2 z_2 z 2 ​ 來轉換線性方程式, { ( x n , y n ) } \{{(x_n,y_n)}\} { ( x n ​ , y n ​ ) } => { ( z n , y n ) } \{{(z_n,y_n)}\} { ( z n ​ , y n ​ ) } 在這空間資料中只要能找線,就可將不同的分類區分,圖中可以線性可以線去做分類。 透過向量方式來轉換成線性方程式 我們找到一個方式將非線性資料X透過向量轉換為Z後,希望透過線性方程式方式來學習,得到正解。 當我們Nonlinear transform轉換成線性方程式,當有新的資料進來我們無法使用invertiable(逆向工程)的方式去轉回非線...