2013年9月11日 星期三

JAVA Reflection:如何取得Class的Super Class、Interfaces..


參考:http://tutorials.jenkov.com/java-reflection/classes.html#superclass

需求:
最近開始研究Spring對於他使用XML可以做DI(Dependency injection)的方式產生了興趣,其中產生bean之後的constructor parameter居然也可以使用XML直接設定而不需要在application中指定id名稱的特性...想來想去也只有Reflection可以辦到了,因此有了以下的小實驗:
我們需要達到兩項目標:
  • 取得指定Class的Super Class
  • 取得指定Class的implement Interface(s)
直接看Code:

我們定義了兩個Interface:ISuperA、ISuperB
 
public interface ISuperA {
}
 
public interface ISuperB {
}

接下來定義implement:
 
public class ImplementClass implements ISuperA, ISuperB {
}

呼叫看結果:
 
 public static void main(String[] args) {
  Class superclass = ImplementClass.class.getSuperclass();
  Class[] interfaces = ImplementClass.class.getInterfaces();
  
  System.out.println("superclass:"+superclass.getName());
  
  System.out.println("interfaces:");
  for(Class interface1 : interfaces)
   System.out.print("\t"+interface1.getName());

 }

結果:
 
superclass:java.lang.Object
interfaces:
 ISuperA ISuperB


補充說明,推測Spring的用法:
下面的Code來自Spring in Action 3rd - Listing 1.4、1.6、1.7:
package com.springinaction.knights;

public classBraveKnightimplementsKnight{
  privateQuestquest;
  public BraveKnight(Questquest){
    this.quest=quest;
  }
  public voidembarkOnQuest()throwsQuestException{
    quest.embark();
  }
}

XML設定:
  
  
    
  

  
  

Spring中呼叫方式如下:
package com.springinaction.knights;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public classKnightMain{
   public staticvoidmain(String[]args){
      ApplicationContextcontext = new ClassPathXmlApplicationContext("knights.xml");
      Knightknight=(Knight)context.getBean("knight");
      knight.embarkOnQuest();
   }
}

依照上述呼叫的Code我們可以看到,指定了XML中的"knight" create...ok這沒甚麼問題,"knight"直接對應到XML的bean id="knight",然而有趣的事情在於,需create的BraveKnight並非是使用default constructor直接建立,是有帶參數的!然而在上述呼叫中卻沒有看到指定bean id="quest"的部分。僅僅是在bean中設定了<constructor-arg ref="quest"/>就對應的到....而quest代表的並非Type型別。
因此如果按照上述的實驗,推測是先取得id="quest"的"com.springinaction.knights.SlayDragonQuest",接者取得"com.springinaction.knights.BraveKnight"中的Constructor,由Reflection機制可以取得各種Constructor的參數型別,只要能找到"一個參數",這裡我們找到的為public BraveKnight(Questquest),因此只要SlayDragonQues符合以下條件之一,那麼XML的指定條件就可成立:

  1. SlayDragonQues的Type為Questquest
  2. Questquest為SlayDragonQuest的super class
  3. Questquest為Interface且被SlayDragonQuest implement
最後答案是3(未列出Questquest Code),因此XML設定正確,可以被順利creation :)

沒有留言:

張貼留言