在对Java的泛型类的变量变化的访问7(Changes in access of variables

2019-06-24 21:37发布

下面是一些代码,编译使用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在测试私有访问

我不明白为什么这不再编译 - 在我的脑海它应该。 可变t是类型的T ,其中必须扩展Test 。 它试图访问该字段_myVar的实例的Test在类的内部Test

事实上,如果我改变方法get(TestContainer<T> container)到下文中,编译(没有警告):

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

我有一个谷歌和甲骨文bug数据库搜索,但没有发现对这个事情...

Answer 1:

§4.9 ...则交点类型具有相同的部件类型(§8)配有一个空体,直接超类Ck和直接超接口T1' ,...,TN”,在同一个包中声明,其中所述出现交叉点型。

从我的那部分JLS的理解,具有可变型你的情况<T extends Test>创建以下交点:

package <the same as of Test>;

class I extends Test {}

因此,当您访问类型的成员T你真正访问路口类型的成员I 。 由于私有成员永远不会被亚型访问这样的构件继承失败,编译错误。 在另一方面访问包私有的(默认)和受保护成员由以下事实的交点是允许

...在其中出现的交叉点型的同一个包中声明。



Answer 2:

见@的答案pi​​ngw33n的评论,但解决这一问题的方法是删除的嵌套类的泛型参数。 除非你有一个使用情况的内部和外部T的可以是不同的,他们是多余的。 他们所做的一切是导致此悲痛。



Answer 3:

对此的解决方法是将泛型实例强制转换为具体的超类声明的私有字段,如

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


文章来源: Changes in access of variables for generic classes in Java 7