Вопрос по generics, java – Изменения в доступе к переменным для универсальных классов в Java 7

17

Вот простой пример кода, который компилируется с использованием 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) метод с ошибкой:

error: _myVar has private access in Test

Я не понимаю, почему это больше не компилируется - по-моему, так и должно быть. Переменнаяt имеет типT, который должен распространятьсяTest, Он пытается получить доступ к полю_myVar экземпляраTest из классаTest.

Действительно, если я поменяю методget(TestContainer<T> container) к следующему, он компилируется (без предупреждений):

public int get(TestContainer<T> container){
  Test t = container.get();
  return t._myVar;
}
Why does this no longer compile? Was this a bug in Java 6? If so why? Is this a bug in Java 7?

У меня был гугл, и я искал в базе данных ошибок Oracle, но ничего по этому поводу не нашел ...

Это была ошибка в Java 6:bugs.sun.com/bugdatabase/view_bug.do?bug_id=7022052 pingw33n
Я удивлен, что это работало в 1.6, пока я не увидел отчет об ошибке. Почему у вас должен быть доступ к закрытому полю экземпляра дочернего класса? brimborium
@ pingw33n, вы должны опубликовать это как ответ. Louis Wasserman
@ pingw33n, и тогда я могу принять это ... хотя, если кто-то, кто лучше понимает JLS, может объяснить «оценку»; раздел отчета об ошибках, я тоже это ценю. amaidment

Ваш Ответ

3   ответа
10

§4.9 ... Then the intersection type has the same members as a class type (§8) with an empty body, direct superclass Ck and direct superinterfaces T1', ..., Tn', declared in the same package in which the intersection type appears.

Из моего понимания этой части JLS, ваш случай с переменной типа<T extends Test> создает следующее пересечение:

package <the same as of Test>;

class I extends Test {}

Поэтому при доступе к членам типаT вы на самом деле доступ к членам типа пересеченияI, Поскольку закрытые члены никогда не наследуются подтипами, доступ к такому члену завершается с ошибкой компиляции. С другой стороны, доступ к закрытым (по умолчанию) и защищенным элементам пакета разрешен тем, что пересечение

... declared in the same package in which the intersection type appears.

0

См. Комментарий @ pingw33n для ответа, но способ исправить это - удалить общие параметры для вложенного класса. Если у вас нет случая использования, когда внутренние и внешние T могут различаться, они являются избыточными. Все, что они делают, вызывает это горе.

Error: User Rate Limit Exceededprivate static class TestContainerError: User Rate Limit Exceededmake a static reference to non-static type T.
Error: User Rate Limit Exceeded amaidment
0

Обходным путем для этого является приведение общего экземпляра к конкретному супертипу, который объявляет приватное поле, например,

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

Похожие вопросы