2009年1月14日水曜日

[Java]リフレクションによるメソッドの取得

このエントリーをはてなブックマークに追加
リフレクションを用いて,特定クラスのメソッドを解析します.
サンプルプログラムでは親クラスから継承しているメソッドは取り除いています.

[調べるクラス Function.java]
import java.util.*;

public class Function {
public static int service(List list, int a ,byte e) throws Exception{
return 1;
}

public void service2(){
}
}


[メソッド情報を保持するクラス MethodInfo.java]
import java.util.List;
import java.util.ArrayList;

public class MethodInfo {
private String    name;   // メソッド名
private String    modifier;  // 修飾子
private List  paramTypes;  // メソッドの引数型の配列
private String    returnType;  // 返り値の型

public MethodInfo(){};

public MethodInfo(String   _name,
String   _modifer,
List _paramTypes,
String   _returnType){
name         = _name;
modifier     = _modifer;
paramTypes   = _paramTypes;
returnType   = _returnType;
}

public void setName(String _name){
name = _name;
}

public void setModifier(String _modifer){
modifier = _modifer;
}

public void setParamTypes(List _paramTypes){
paramTypes = _paramTypes;
}

public void setReturnType(String _returnType){
returnType = _returnType;
}

public String getName(){
return name;
}

public String getModifier(){
return modifier;
}

public List getParamTypes(){
return paramTypes;
}

public String getReturnType(){
return returnType;
}

public String toString(){
String str =  "Modifier : " + modifier + "\n";
str += "Name : " + name + "\n";
str += "Params : " + paramTypes.toString() + "\n";
str += "Retrun : " + returnType;
return str;
}
}


[解析実行クラス MethodAnalyzer.java]
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;

public class MethodAnalyzer {
private String className;
public MethodAnalyzer(String _className){
className = _className;
}

/**
* クラスのメソッド一覧を取得する
* @param cls
* @return 
*/
private List getMethodList(Class cls){
List list = new ArrayList();
Method[] methods = cls.getMethods();
for(Method method : methods){
list.add(method);
}
return list;
}

/**
* 親クラスのメソッド一覧を取得する
* @param clas
* @return
*/
private List getParentMethodList(Class cls){
return getMethodList(cls.getSuperclass());
}

/**
* 第1引数から第2引数に存在するMethodを削除する
* @param list1
* @param list2
*/
private void removeMatchList(List list1, List list2){
for(Method method : list2){
if(list1.indexOf(method) != -1){
list1.remove(method);
}
}
}

/**
* リフレクションを用いて,クラスを解析する.
* @return MethodInfo[]
*/
public MethodInfo[] analyze(){
// メソッド情報を保持
MethodInfo[] methodInfos = null;
try{
// 親クラスには存在せず,自クラスのみに存在するメソッドを抽出
Class cls = Class.forName(className);
List methodList = getMethodList(cls);
removeMatchList(methodList, getParentMethodList(cls));

// メソッド情報配列の領域確保
methodInfos = new MethodInfo[methodList.size()];

for(int i = 0 ; i < methodList.size(); i++){
// メソッド情報配列の初期化
methodInfos[i] = new MethodInfo();

// 修飾子を取得&格納
methodInfos[i].setModifier(Modifier.toString(methodList.get(i).getModifiers()));

// 戻り値の型を取得&格納
methodInfos[i].setReturnType(methodList.get(i).getReturnType().getName());

// メソッド名を取得&格納
methodInfos[i].setName(methodList.get(i).getName());

// 引数の型を取得&格納
Class[] params = methodList.get(i).getParameterTypes();
List paramTypes = new ArrayList();
for(Class c : params){
paramTypes.add(c.getName());
}
methodInfos[i].setParamTypes(paramTypes); 
}
} catch (ClassNotFoundException cnfe){
cnfe.printStackTrace();
}
return methodInfos;
}

// 使用例
public static void main(String[] args) {
MethodAnalyzer ma = new MethodAnalyzer("Function");
MethodInfo[] mis = ma.analyze();

for(MethodInfo mi : mis){
System.out.println(mi.toString() + "\n");
} 
}
}



[実行結果]
Modifier : public
Name : service2
Params : []
Retrun : void

Modifier : public static
Name : service
Params : [java.util.List, int, byte]
Retrun : int