次のコードはJava 1.6で問題なくコンパイルできますが、Java 1.7ではコンパイルできません。どうして?なぜこのコードはJava 1.6ではコンパイルされますが、Java 1.7ではコンパイルされませんか?
コードの関連部分は、プライベートの「データ」フィールドへの参照です。参照は、フィールドが定義されている同じクラス内からのものであり、合法的に見えます。しかし、それは一般的に型付けされた変数を介して起こっている。このコードは、社内のライブラリのクラスに基づく抜粋された例で、Java 1.6で動作しましたが、Java 1.7では動作しません。
私はこれを回避する方法を求めていません。私はすでにそれをしています。なぜこれがもううまくいかないのか解明しようとしています。三つの可能性が頭に浮かぶ:
- このコードではなく法的はJLSに応じてコンパイルされなかったんです
- このコードは法的である(1.7で修正された1.6コンパイラのバグがありました) JLSに応じてコンパイルすべきである(下位互換性のバグが1.7コンパイラに導入された)
- このコードはJLS
Foo.java:
import java.util.TreeMap;
import java.util.Map;
public abstract class Foo<V extends Foo<V>> {
private final Map<String,Object> data = new TreeMap<String,Object>();
protected Foo() { ; }
// Subclasses should implement this as 'return this;'
public abstract V getThis();
// Subclasses should implement this as 'return new SubclassOfFoo();'
public abstract V getEmpty();
// ... more methods here ...
public V copy() {
V x = getEmpty();
x.data.clear(); // Won't compile in Java 1.7
x.data.putAll(data); // "
return x;
}
}
コンパイラ出力:
> c:\tools\jdk1.6.0_11\bin\javac -version
javac 1.6.0_11
> c:\tools\jdk1.6.0_11\bin\javac c:\temp\Foo.java
> c:\tools\jdk1.7.0_10\bin\javac -version
javac 1.7.0_10
> c:\tools\jdk1.7.0_10\bin\javac c:\temp\Foo.java
Foo.java:18: error: data has private access in Foo
x.data.clear();
^
Foo.java:19: error: data has private access in Foo
x.data.putAll(data);
^
2 errors
補遺。参照がプライベートメンバ変数の代わりにプライベートメソッドにある場合、同じ問題が発生します。これはJava 1.6では動作しますが、1.7では動作しません。
Foo2.java:
import java.util.TreeMap;
import java.util.Map;
public abstract class Foo2<V extends Foo2<V>> {
private final Map<String,Object> data = new TreeMap<String,Object>();
protected Foo2() { ; }
// Subclasses should implement this as 'return this;'
public abstract V getThis();
// Subclasses should implement this as 'return new SubclassOfFoo();'
public abstract V getEmpty();
// ... more methods here ...
public V copy() {
V x = getEmpty();
x.theData().clear(); // Won't compile in Java 1.7
x.theData().putAll(data); // "
return x;
}
private Map<String,Object> theData() {
return data;
}
}
コンパイラ出力:
> c:\tools\jdk1.6.0_11\bin\javac c:\temp\Foo2.java
> c:\tools\jdk1.7.0_10\bin\javac c:\temp\Foo2.java
Foo2.java:18: error: theData() has private access in Foo2
x.theData().clear();
^
Foo2.java:19: error: theData() has private access in Foo2
x.theData().putAll(data);
^
私は生成されたクラスファイルを両方とも逆コンパイルすることをお勧めします。違いが明らかになるはずです。 – Landei
@Landeiコンパイラがコンパイルを拒否しているため、1.7のケースに生成されるクラスファイルはありません。 –