17

これは、Java 6を使用してコンパイルするが、Java7ではコンパイルしないコードの簡単な例です。

public class Test<T extends Test> {

  private final int _myVar;

  public Test(int myVar) {
    _myVar = myVar;
  }

  public int get(TestContainer<T> container){
    T t = container.get();
    return t._myVar;
  }

  private static class TestContainer<T extends Test> {
    private final T _test;
    private TestContainer(T test) {
      _test = test;
    }
    public T get(){
      return _test;
    }
  }
}

get(TestContainer<T> container)Java 7では、メソッドでのコンパイルに失敗し、次のエラーが発生します。

エラー:_myVarはテストでプライベートアクセスを持っています

なぜこれがコンパイルされなくなったのか理解できません-私の考えではそうすべきです。変数tはタイプTであり、拡張する必要がありますTest。クラス内から_myVarのインスタンスのフィールドにアクセスしようとしています。TestTest

実際、メソッドget(TestContainer<T> container)を次のように変更すると、コンパイルされます(警告なしで)。

public int get(TestContainer<T> container){
  Test t = container.get();
  return t._myVar;
}
  • なぜこれがコンパイルされなくなったのですか?
  • これはJava6のバグでしたか?もしそうなら、なぜですか?
  • これはJava7のバグですか?

私はグーグルを持っていて、Oracleバグデータベースで検索しましたが、これについては何も見つかりませんでした...

4

3 に答える 3

10

§4.9 ...次に、交差型は、空の本体、直接スーパークラスCk、および直接スーパーインターフェイスT1'、...、Tn'を持ち、同じパッケージで宣言されたクラスタイプ(§8)と同じメンバーを持ちます。交差点タイプが表示されます。

そのJLS部分についての私の理解から、型変数を使用したケースで<T extends Test>は、次の交差点が作成されます。

package <the same as of Test>;

class I extends Test {}

したがって、タイプのメンバーTにアクセスすると、実際には交差タイプのメンバーにアクセスしますI。プライベートメンバーはサブタイプに継承されないため、そのようなメンバーへのアクセスはコンパイルエラーで失敗します。一方、パッケージプライベート(デフォルト)および保護されたメンバーへのアクセスは、交差点が

...交差型が表示されるのと同じパッケージで宣言されています。

于 2012-05-29T12:16:10.670 に答える
0

答えについては@pingw33nのコメントを参照してください。ただし、これを修正する方法は、ネストされたクラスのジェネリックパラメーターを削除することです。内側と外側のTが異なる可能性があるユースケースがない限り、それらは冗長です。彼らがしているのは、この悲しみを引き起こしているだけです。

于 2012-05-29T03:46:18.483 に答える
0

この回避策は、汎用インスタンスをプライベートフィールドを宣言する具象スーパータイプにキャストすることです。

public int get(TestContainer<T> container){
  T t = container.get();
  return ((Test) t)._myVar;
}
于 2014-03-14T22:27:43.737 に答える