読者です 読者をやめる 読者になる 読者になる

感謝のプログラミング 10000時間

たどり着いた結果(さき)は、感謝でした。

はてブでコメントをいただいたので、さっそくSpring Frameworkでリフレクションを使ってる部分を読んでみた。

<スポンサーリンク>

昨日リフレクションを勉強して記事を書いたら、
id:nemobaさんがアドバイスをしてくださった。

SeasarとかSpringのコードも見ると、利用方法とかもわかってさらに便利。まずは利用してみれば、見ることになるから。

ありがとうございます!

早速、Spring Frameworkのソースを読んでみると、たくさんのリフレクションのサンプルがあった。
https://github.com/spring-projects/spring-framework
このGitHubの中の、「org.springframework.util」のReflectionUtilsクラス。

パーフェクトJavaを読むだけでは真似できるサンプルが足りなくて、理解があまり進まなかった。
しかし、ここには宝の山が・・・。

Authorに輝く「Rod Johnson」の名。
自分の中では教科書の太字になって出てくるような人物だ。

こんな人のソースを実際に見ることができるなんて。
オープンソースって素晴らしい。

自分はプログラミングは独学もいいとこで、勉強の仕方も確立できていなかった。

だからとりあえず知らない用語を見つけたら、すぐに本を買って、できるだけ体系的に勉強しようとした。

それが一番早いと信じていた。

でも、体系的に教科書を読むだけではなく、実際に「生きたコード」を読むっていうのがすごく勉強になることが改めてわかった。
これからは基礎を勉強しつつも、生きたコードを読むことに決めた。

nemobaさん、ありがとうございました。

引数にクラスとメソッドを指定して、それを実行するサンプル

で、SpringのReflectionUtilsを見ながら、真似をしてみた。
まず、このサンプルでターゲットにするためだけのペラクラス。

package opensrc;

public class Hello {
    private String message = "Yahoo!!";
    private String myName = "google";
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public String getMyName() {
        return myName;
    }
    public void setMyName(String myName) {
        this.myName = myName;
    }
    
    public void sayHello() {
        System.out.println(message);
    }
    
    public void sayMyName() {
        System.out.println(myName);
    }
}

こいつをnew Hello();しないで、外から(=引数)こいつの名前を指定して、メソッドを実行してみる。

どうやるかというと、こんな感じ。

package opensrc;

import java.lang.reflect.Method;

public class ReflectionSample {
    public static Object invokeMethod(Method method, Object target) {
        try {
            return method.invoke(target);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        throw new IllegalStateException("Should never get here");
    }
    
    public static Method findMethod(Class<?> clazz, String name) {
        Class<?> searchType = clazz;
        while (searchType != null) {
            Method[] methods = (searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods());
            for (Method method : methods) {
                if (name.equals(method.getName())) {
                    return method;
                }
            }
            searchType = searchType.getSuperclass();
        }
        return null;
    }
    public static void main(String[] args) throws Exception {
        //引数チェックは省略
        String targetClassName = args[0];
        String targetMethodName = args[1];
        Class clazz = Class.forName(targetClassName);
        Method targetMethod = findMethod(clazz, targetMethodName);
        System.out.println("対象のクラスは:" + clazz.getName());
        System.out.println("実行するメソッドは:" + targetMethod.getName());
        System.out.println("メソッドを実行するよ!結果↓");
        invokeMethod(targetMethod, clazz.newInstance());
    }
}

これに引数「"opensrc.Hello", "sayHello"」というように、クラス名、メソッド名を渡して実行する。
すると・・・

対象のクラスは:opensrc.Hello
実行するメソッドは:sayHello
メソッドを実行するよ!結果↓
Yahoo!!

なんと、引数で指定したメソッドを実行することができた。

次はフィールドをセットするところも真似してみたい。

ついでに、家に積んでた「オープンソースの育て方」っていう本も読み進めようと思う。