kazurof weblog

技術ネタのメモを並べます

oracleのjavacとEclipseのJavaコンパイラの挙動の相違点

結論

アノテーションの要素を変数で設定するときの変数(あるいはフィールド)名と、メソッドのパラメータ名は別のものにしましょう。

以下のコードはEclipseではコンパイル・実行ともに可能。

gistb407368a712f4006ecea

しかし、javacコンパイラではエラーになる。 *1

Java7の場合

>javac -version ECJProblem.java  
javac 1.7.0_55    
ECJProblem.java:7: エラー: 属性の値は定数である必要があります  
  public String doSomething(@TestAnnotation(nantoka) String nantoka) {  
                                            ^
エラー1個

Java8の場合

>javac -version ECJProblem.java
javac 1.8.0
ECJProblem.java:7: エラー: 要素値は定数式である必要があります
  public String doSomething(@TestAnnotation(nantoka) String nantoka) {
                                            ^
エラー1個

原因(と思われるもの)

doSomethingメソッドにおいて、要素値をフィールドnantokaを使って設定しようとしていますが、 同時にメソッドパラメータにも同じ名前が使われています。 Eclipseの場合、要素値への設定はクラスのフィールドからされているとみなされるようですが、 javacの場合、メソッドパラメータからなされているとみなされるようです。

この違いで問題になる(と思われる)パターン

いつもEclipseを使ってビルドしていたが、緊急にエラーを直さなくてはならない。いつもの手順でEclipseでシステム全体をビルドするのではなくjavacコマンドで必要なファイルをコンパイルしてclassファイルだけ差し替えたい。しかし実際にそれを行うと、本現象にてjavacではコンパイルできないのでシステムの修正ができない。

予防的にとれる対策

アノテーションの要素値に設定する変数名とメソッドのパラメータ名は別にしましょう。

検証した環境など

  • Eclipse Version: Kepler Service Release 2 Build id: 20140224-0627
  • Windows7
  • Java7 Java8

*1:Java7とJava8でエラーメッセージ文言が微妙に異なるのでググられることを意図して両方載せてみる。