Java 7 中泛型类的变量访问更改

下面是一些使用 Java 6 编译但未在 Java 7 中编译的代码的简单示例。

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;
    }
  }
}

在Java 7中,它无法在方法中编译,并出现错误:get(TestContainer<T> container)

错误:_myVar在测试中具有私有访问权限

我不明白为什么这不再编译 - 在我看来它应该。变量的类型为 ,必须扩展 。它正在尝试从类中访问 的实例的字段。tTTest_myVarTestTest

实际上,如果我将方法更改为以下内容,它将编译(没有警告):get(TestContainer<T> container)

public int get(TestContainer<T> container){
  Test t = container.get();
  return t._myVar;
}
  • 为什么它不再编译?
  • 这是 Java 6 中的一个错误吗?如果是,为什么?
  • 这是Java 7中的一个错误吗?

我有一个谷歌并在Oracle错误数据库中搜索,但没有找到任何东西......


答案 1

§4.9 ...然后,交集类型具有与类类型 (§8) 相同的成员,该类类型具有空主体、直接超类 Ck 和直接超接口 T1', ..., Tn',在出现交集类型的同一包中声明。

根据我对JLS部分的理解,您使用类型变量的情况会创建以下交集:<T extends Test>

package <the same as of Test>;

class I extends Test {}

因此,当您访问该类型的成员时,您实际上访问了交集类型 的成员。由于私有成员永远不会被子类型继承,因此访问此类成员会失败并出现编译错误。另一方面,允许访问包专用(默认)和受保护成员,因为交集TI

...在显示交集类型的同一包中声明。


答案 2

有关答案,请参阅@pingw33n的注释,但解决此问题的方法是删除嵌套类上的泛型参数。除非你有一个用例,其中内部和外部T可以不同,否则它们是多余的。他们所做的一切都是造成这种悲伤。


推荐