Java 7中泛型类变量访问的变化

ama*_*ent 17 java compiler-construction generics access-modifiers 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;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

我不明白为什么这不再编译 - 在我看来它应该.变量t是类型T,必须扩展Test.它试图从类中访问_myVar实例的字段.TestTest

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

public int get(TestContainer<T> container){
  Test t = container.get();
  return t._myVar;
}
Run Code Online (Sandbox Code Playgroud)
  • 为什么这不再编译?
  • 这是Java 6中的错误吗?如果是这样的话?
  • 这是Java 7中的错误吗?

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

pin*_*33n 10

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

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

package <the same as of Test>;

class I extends Test {}
Run Code Online (Sandbox Code Playgroud)

因此,当您访问该类型的成员时,T您实际访问该交集类型的成员I.由于私有成员永远不会被子类型继承,因此访问此成员会因编译错误而失败.另一方面,交叉点允许访问package-private(默认)和受保护成员

...在交叉类型出现的同一个包中声明.