Не удается найти параметр типа, если он является внутренним классом подкласса в Java
Почему следующий код имеет ошибку компиляции:
Foo.java:
public abstract class Foo<T> {
public abstract T getInner();
}
MyFoo.java:
public class MyFoo extends Foo<MyFooInner> {
public static class MyFooInner {
}
public MyFooInner getInner() {
return new MyFooInner();
}
}
Компиляция результатов второго класса:
MyFoo.java:1: cannot find symbol
symbol: class MyFooInner
public class MyFoo extends Foo<MyFooInner> {
^
1 error
Есть ли способ обойти эту проблему, помимо помещения внутреннего класса в свой собственный файл?
Ответы
Ответ 1
Используйте следующие обозначения:
public class MyFoo extends Foo<MyFoo.MyFooInner> {...
UPDATE. Статические вложенные классы фактически являются классом верхнего уровня, как указано здесь:
Статический вложенный класс взаимодействует с членами экземпляра его внешнего класса (и других классов), как и любой другой класс верхнего уровня. В эффект, статический вложенный класс поведенчески является классом верхнего уровня, который был помещен в другой класс верхнего уровня для удобства упаковки.
Итак, единственный способ ссылаться на статический вложенный класс - это где-то упоминать его родительский класс. В противном случае это ссылка на импортированный класс или класс внутри одного пакета.
UPDATE. Чтобы объяснить это еще раз, другим способом ссылки на класс является его импорт следующим образом:
import my.package.MyFoo.MyFooinner;
public class MyFoo extends Foo<MyFooInner> {...
Ответ 2
Чтобы основываться на @Andrey Adamovich answer, причина этого в том, что типы, идентифицированные в объявлении класса, должны иметь смысл для членов вне этого класса. Это то же самое, как если бы я
записал следующее в другом файле класса:
MyFooInner mfi = new MyFooInner()
Это не скомпилировалось бы, потому что этот класс не знал бы, что MyFooInner
было - я либо должен был бы квалифицировать его, написав MyFoo.MyFooInner
, либо использовать import MyPackage.MyFoo.MyFooInner;
. Эта же логика применяется к объявлениям классов.
По той же причине вложенные классы, объявленные private
, вообще не могут использоваться в объявлении родительского класса.