Почему Java-компилятор (в частности, его синтаксический анализатор) не может понять это утверждение
У меня есть следующие два класса (в двух отдельных файлах).
public class Foo
{
public static class A
{
public static final boolean FLAG = false;
}
public final A A = new A();
}
public class Bar
{
void method()
{
if (Foo.A.FLAG) <<<< this is giving "Cannot make static ref to non-static field
// do something
;
}
}
Мой вопрос: почему компилятор не может распознать, что под Foo.A
я имел в виду класс A
, а не член, который также называется A
?
Ответы
Ответ 1
Это называется obscuring, скрытая функция/ограничение Java
Простое имя может возникать в контекстах, где это может быть потенциально интерпретируется как имя переменной, типа или пакета. В этих ситуации, правила § 6.5 указывают, что будет выбрана переменная в предпочтении к типу, и что тип будет выбран в предпочтении к пакету. Таким образом, иногда бывает невозможно ссылаться на видимый тип или объявление пакета через его простое имя. Мы говорим, что такая декларация скрыта.
Если переменная A
была static
, она будет скомпилирована, поскольку вы можете получить доступ к элементам static
в ссылках на объекты.
Также FLAG
не был инициализирован.
Ответ 2
Некоторые способы доступа к флагом:
<Foo_A extends Foo.A> void test1()
{
if(Foo_A.FLAG)
;
}
void test2()
{
class Foo_A extends Foo.A{}
if(Foo_A.FLAG)
;
}
-------------------------------------
import pkg.Foo.A;
public class Bar
{
void test3()
{
if(A.FLAG)
;
}
}
в этих контекстах, "Foo.A"
может быть интерпретирован только как тип, а не переменная.
Ответ 3
Поскольку для внутренних классов требуется экземпляр закрывающего типа. Если у вас нет экземпляра Foo, A не существует.
Изменить - это неверно, но причина, по которой это информативно. см. ниже: