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

この日記は私的なものであり所属会社の見解とは無関係です。 GitHub: takahashikzn

ECJではOKで、javacだとNGな例

EclipseのコンパイラとJDKのコンパイラは別物です。
ECJでコンパイルできても、javacでコンパイルできないことがあります。


では、どんなケースがjavacではダメなのか。
その一部を紹介します。

ケース1: アノテーションの属性値配列の、最後の要素のカンマ

@Foo(value = { 
    "a", 
    "b",  //← カンマありなしで違う
} )
public class Hoge {
}


このソースは、ECJではコンパイルできますがjavacだとダメです。

Hoge.java:7: 式の開始が不正です。
@Foo(value = { 
    "a", 
    "b",
} )
^
public class Hoge {

ケース2: Genericsにおける子クラスへのキャスト


例えば、Generation Gapパターンを使った場合、次のようなコードを書きたくなることがあります。

//自動生成したクラス
class AbstractFoo<T extends AbstractFoo<T>> implements Comparable<Foo> {
    public int compareTo(Foo that) {
        final Foo thisFoo = (Foo) this;

        // 何でもいいけど例えばこんな感じ
        return thisFoo.hashCode() - that.hashCode();
    }
}


//自分で手を入れる用クラス
class Foo extends AbstractFoo<Foo> {
}


これはECJではOKですが、javacだと次のようなエラーになります。

Test.java:5: 変換できない型
検出値  : AbstractFoo<T>
期待値  : Foo
                final Foo thisFoo = (Foo) this;
                                          ^
エラー 1 個


この場合は次のようにすればOKです。

class AbstractFoo<T extends AbstractFoo<T>> implements Comparable<Foo> {
    public int compareTo(Foo that) {
        final Foo thisFoo = Foo.class.cast(this); //ここを修正

        return thisFoo.hashCode() - that.hashCode();
    }
}


class Foo extends AbstractFoo<Foo> {
}