Подтвердить что ты не робот

JDK 1.7 vs JDK 1.6 внутренняя разница наследования классов

Я решаю некоторые головоломки Java и наткнулся на это:

public class Outer {
    class Inner1 extends Outer {}
    class Inner2 extends Inner1 {}
}

При компиляции этого кода с javac 1.6.0_45 я получаю, как и ожидалось, эту ошибку:

Outer.java:8: cannot reference this before supertype constructor has been called
class Inner2 extends Inner1 {}                                                                                                
^

Это из-за того, что компилятор генерирует конструктор по умолчанию для класса Inner2 с похожим кодом, что объясняет ошибку выше:

Inner2 () {
    this.super();
}

И теперь это очевидно, потому что вы действительно не можете сделать это в Java 1.6.0_45, JLS 8.8.7.1 (как я могу догадаться):

Явный оператор вызова конструктора в теле конструктора может не ссылаются на какие-либо переменные экземпляра или методы экземпляра, объявленные в этот класс или любой суперкласс, или использовать это или супер в любом выражении; в противном случае возникает ошибка времени компиляции.

См. (принятый ответ в Нечетная ситуация для "не может ссылаться на это до того, как был создан конструктор супертипа" )

Но если я попытаюсь скомпилировать его с помощью javac 1.7.0_79 - это нормально!

И вот вопрос: Что изменилось в Java 1.7, что этот код теперь корректен?

Спасибо заранее!

4b9b3361

Ответ 1

Похоже, что обсуждалась та же проблема, что и ошибка JDK-6708938: Синтетический вызов супер-конструктора никогда не должен использовать 'this' как квалификатор в отладчике ошибок Java.

Также я считаю, что было бы здорово взглянуть на другие связанные с ним предыдущие проблемы, например JDK-4903103: невозможно компилировать подклассы внутренних классов.

Обратите внимание на фиксированные версии обеих ошибок.

И как результат, посмотрите Обзор обслуживания JSR 901 (спецификация языка Java) для Java SE 7.

Из Третья версия спецификации языка Java

В противном случае S является внутренним классом-членом (§8.5). Это время компиляции если S не является членом лексически закрывающего класса или суперкласса или его суперинтерфейса. Пусть O является самым внутренним лексическим охватывающий класс которого S является членом, и пусть n является целым числом таких что O является n-м лексически охватывающим классом C. Немедленно охватывающий экземпляр i по отношению к S является n-м лексическим охватывающий экземпляр этого.

И из обзора обслуживания JSR 901 (Java Language Specification) для Java SE 7 (полная версия, страница 242, синий текст) или же в Java Language Specification, Java SE 7 Edition (непосредственно перед разделом 8.8.8)

В противном случае S является внутренним классом-членом (§8.5).

Пусть O - самый внутренний лексически охватывающий класс S, n - целое число, такое, что O n-й лексически охватывающий класс C.

Немедленно вставляя экземпляр я по S является n-й лексически охватывающей экземпляр этого.

Итак, вы можете видеть, что часть с ошибкой времени компиляции прошла.

Ответ 2

Я подозреваю, что это связано с invoke dynamic, который был добавлен в java 1.7 для подготовки к лямбда в java 8.