2013-06-13 2 views
4

Следующий код компилируется, как и ожидалось:Странная ошибка компиляции с внутренними классами

class A { 
    class B {} 
    class C extends B {} 
} 

Но, если у нас есть класс B расширить класс A, мы получаем ошибку компиляции:

class A { 
    class B extends A {} 
    class C extends B {} // <-- Error here 
} 
 
No enclosing instance of type A is available due to some intermediate 
constructor invocation. 

Что здесь происходит? Почему расширение A что-то изменит?

EDIT: По-видимому, это прекрасно компилируется на Java 7. Я хотел бы получить объяснение относительно того, почему он не скомпилирован в старых версиях Java и что было изменено в Java 7, чтобы это разрешить.


ТАКЖЕ:

+0

Пожалуйста, забудьте про весь вздор - это ошибка. В этом случае Джавак отлично работает. Я отредактировал свой ответ. https://bugs.eclipse.org/bugs/show_bug.cgi?id=373371 –

+0

@ ZiyaoWei Это также не работает в IntelliJ – arshajii

+0

Javac 7 должен работать, а если нет, добавление конструктора поможет. –

ответ

5

Поскольку B не является статичным, он необходим экземпляр A, чтобы иметь возможность существовать, таким образом, ошибка.

Если B является статическим, ошибка уходит.

Ах, забудьте о ерунде. Это bug, и он работает на ideone в режиме Java7. Тем не менее, до Java 7 не работает - see this question, и вам необходимо либо

  1. Изменение B статического

  2. Добавить конструктор

    C() { 
        A.this.super(); 
    } 
    

А потом его будем работать.

Причина, почему это происходит, прежде чем Java 7 может быть следующее что из JLS:

Let C be the class being instantiated, let S be the direct superclass of C, and let i be the instance being created.

неявной super вызывается непосредственно вмещающих экземпляр I относительно S.

В earlier JLS, экземпляр немедленно ограждающий определяются как

Let O be the innermost lexically enclosing class of which S is a member, and let n be an integer such that O is the nth lexically enclosing class of C. The immediately enclosing instance of i with respect to S is the nth lexically enclosing instance of this.

Однако в Java 7:

Let O be the innermost lexically enclosing class of S, and let n be an integer such that O is the n'th lexically enclosing class of C.

The immediately enclosing instance of i with respect to S is the n'th lexically enclosing instance of this.

Таким образом, в прошлом это было сокровенным лексический объемлющий классом из которых S является член, а теперь это самый внутренний лексически охватывающий класс S, поэтому он изменился с C до A, поэтому код работает на Java 7.

+0

Второе - это как вызов себя снова, который заставит его называть себя бесконечно. Рекурсивный. – johk95

+0

@arshajii Протестировано на ideone, работает в Java7. –

1

Это рекурсия.
Если B расширяет A, и А имеет новый B самого по себе, так что B протянет еще раз, и так далее ...

Как отметил @ZiyaoWei ошибка уходит, когда В static. Это потому, что тогда класс B будет существовать только один раз.

Смежные вопросы