アノテーション入門勉強会を開催してきた。

DoorKeeper
https://kumamotojava.doorkeeper.jp/events/42272

当日の資料
https://github.com/megascus/annotation-handson


ちょっと間が空いてしまった*1けれども、先日熊本にてアノテーション入門という名前で勉強会を開いてきた。

最近のJavaフレームワークはたいていアノテーションが使用されているが、アノテーションが何やってるかよく判らないよねぇという声が聞こえたので。
とりあえず、目標地点としてDIを見据えて、アノテーションを使って何か作れるようにと、アノテーションがいかに何もしていないのかが判るように行ったつもりです。

とはいっても、DIについてはきしださんがこの勉強会を告知した後にDIを自分で実装してみるという記事を書いてくださったので、とりあえず、そちらの前提条件となる知識を網羅できるようにしました。
http://d.hatena.ne.jp/nowokay/20160406

DIまでやっていたら2時間じゃ終わらなかったと思うのでちょうどよかった。

リフレクションは難しい

勉強会で躓く人が多かったのはやはりリフレクションでした。
Javaアノテーションはリフレクション経由でアクセスするためリフレクションに対する知識は必須となります。

JavaのコードをJava言語というか、JVMがどのように扱っているのかをダイレクトに扱う必要があるため、リフレクションを使用せずに書いたコードとリフレクションを使用して書いたコードは多くの場合乖離します。

古くから使われているライブラリでもよくこの罠を踏んでいる場合があって、たとえば、以下のコードはメソッドが取得できず、意図した通りには動きません。

public class Sample {

    public Method getMethod() throws Exception {
        Class<Bean> clazz = Bean.class;
        return clazz.getMethod("getSuperProperty");
    }
}

class SuperBean {
    String getSuperProperty();
}

class Bean extends SuperBean {
    String getSubClassProperty();
}

以下のように記載する必要があります。

public class Sample {

    public Method getMethod() throws Exception {
        Class<?> clazz = Bean.class;
        do {
  
            try {
                return clazz.getMethod("getSuperProperty");
            } catch (NoSuchMethodException ex) {
            }
        } while ((clazz = clazz.getSuperclass()) != null);
        throw new NoSuchMethodException("method not found.");
    }
}


Javaのコードを書くときはサブクラスでもスーパークラスのメソッドを直接取得できますが、リフレクションでは一度スーパークラスを経由しないとメソッドを取得することが出来ません。

Java内部ではサブクラスとスーパークラスが分けて管理されているという証拠なのですが、まあ、なんというか、直感とはぶれますね。

とか、いろいろとあり難しい。

アノテーション自体はリフレクションだけ理解できればそのままなので、まあ、楽です。

*1:地震のため