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

Почему 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?

4b9b3361

Ответ 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 не существует.

Изменить - это неверно, но причина, по которой это информативно. см. ниже: