2013年8月25日 星期日

Java Reflection - 存取Field 資訊

參考:Java 學習筆記 (10) - Reflection

因為摸了MyBatis(請見MyBatis - 基本安裝 + 使用Select)後對於他可以利用Xml可以做各種設定以及回傳對應Data的方式相當感興趣,直覺是使用Reflection機制實做,因此有了這篇小實驗 :)

需求:假設我們有一個User Class如下,我們需要能
  • 需求1 - 取得指定所有Public的Field資訊
  • 需求2 - 取得指定指定的Declare的Field資訊(包含private、protected)
 
public class User {
 private String userid;
 private String name;
 private String password;
 private String email;
  //...other
}

  1. 取得指定Class中所有Public的Field資訊(由於以上的User Class沒有任何public field,因此只列出使用方式)
        Class aClass = User.class;
        Field[] publics = aClass.getFields();
    
  2. 取得指定指定的Declare的Field資訊(包含private、protected)
    假設我們現在想要取得其中的userid與email,並對他其中一個已存在的實體Instance做修改,怎麼做?:
    • 取得User Class的useir、email Field:
        Class aClass = User.class;
        Field fuserid = aClass.getDeclaredField("userid"); 
        Field femail = aClass.getDeclaredField("email"); 
        fuserid.setAccessible(true);
        femail.setAccessible(true);
      
      由於我們希望能修改其中的內容,因此記得要呼叫setAccessible(true),讓該field可以被修改
    • 對已建立的實體Instance進行修改:
         Constructor cons = aClass.getConstructor(null);
         User u = (User) cons.newInstance(null);
         fuserid.set(user, "ifAfter");
         femail.set(user, "mail@After.com");

以下為完整範例:

  • User.java
    package cmpnts;
    
    public class User {
     private String userid;
     private String name;
     private String password;
     private String email;
    
     public String getUserId() {
      return userid;
     }
    
     public void setUserId(String userid) {
      this.userid = userid;
     }
    
     public String getName() {
      return name;
     }
    
     public void setName(String username) {
      this.name = username;
     }
    
     public String getPassword() {
      return password;
     }
    
     public void setPassword(String pwd) {
      this.password = pwd;
     }
     
     public String getEmaill(){
      return email;
     }
     
     public void setEmaill(String mail){
      email = mail;
     }
     
     @Override
     public String toString(){
      StringBuffer buf = new StringBuffer();
      buf.append("UserId:").append(this.getUserId());
      buf.append("\r\n\tname:").append(this.getName());
      buf.append("\r\n\tpassword:").append(this.getPassword());
      buf.append("\r\n\temail:").append(this.getEmaill());
      return buf.toString();
     }
    }
    
  • FieldReflectionTest.java:
    package reflection;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    
    import cmpnts.User;
    
    public class FieldReflectionTest {
    
     public static void main(String[] args) {
      User user = new User();
      user.setUserId("idBefore");
      user.setName("name");
      user.setPassword("password");
      user.setEmaill("mail@before.com");
      
      try {
       alterFieldUserIdEmail(user);
      } catch (Exception e) {
       e.printStackTrace();
      }
     }
     
     public Field[] getPublicFields(){
      Class aClass = User.class;
      Field[] publics = aClass.getFields();
      return publics;
     }
     
     public static void alterFieldUserIdEmail(User user) throws Exception{
      System.out.println(user);
      
      Class aClass = User.class;
      Field fuserid = aClass.getDeclaredField("userid"); 
      Field femail = aClass.getDeclaredField("email"); 
      fuserid.setAccessible(true);
      femail.setAccessible(true);
      
      Constructor cons = aClass.getConstructor(null);
      User u = (User) cons.newInstance(null);
      fuserid.set(user, "idAfter");
      femail.set(user, "mail@After.com");
      System.out.println(user);
     }
    
    }
    


  • 執行結果:
    UserId:idBefore
    name:name
    password:password
    email:mail@before.com

    UserId:idAfter
    name:name
    password:password
    email:mail@After.com

    修改成功!!

    沒有留言:

    張貼留言