Почему я могу снова успешно объявить статическое поле внутри main() в Java?

Я объявил private static double fd, а затем снова объявил double fd внутри main(). Почему я могу скомпилировать и запустить его успешно?

    public class HelloWorld {
    private static double fd = 1.0;

    public static void main(String[] args){
        System.out.println(fd); //1.0
        double fd = 2.0;
        System.out.println(fd); //2.0


    }
}

ты не. вы объявляете локальную переменную, которая имеет то же имя, что и ваша статическая переменная

Stultuske 10.04.2019 08:36

И просто для развлечения и путаницы вы можете объявить локальный fd с типом, отличным от статического fd. А также для еще большего удовольствия вы можете использовать fd в собственном инициализаторе: double fd = fd = 2.0;.

Andy Turner 10.04.2019 08:39

Ответ таков: потому что разработчики Java решили сделать это возможным.

JB Nizet 10.04.2019 08:42

@JBNizet, теперь, когда вы подняли этот вопрос, я вижу, что вы правы. Я считаю, что это наследие C/C++, но они могли просто решить, что это ошибка компилятора. Итак, учитывая сомнительную полезность и склонность к ошибкам этой «функции», почему было решено разработать спецификации именно таким образом?

Sharon Ben Asher 10.04.2019 08:57

Потому что это чрезвычайно полезно, например, иметь возможность делать такие вещи, как this.name = name.

JB Nizet 10.04.2019 09:03
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
5
66
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Переменная фд имеет область действия функции, подумайте, компилятор сначала проверяет ближайшую к ней область, а затем, если он не находит там, он пытается проверить глобальную область видимости, если он нашел что-то в локальной области видимости, он напечатает это, или else переходит к проверке другой области.

Ответ принят как подходящий

Это не синтаксическая ошибка (хотя это, вероятно, приведет к логической ошибке, багу). Компилятор без проблем скомпилирует этот код. Второе объявление double fd создает локальную переменную для основного метода. Область действия этой переменной начинается с ее объявления и заканчивается в конце блока (как и для всех локальных переменных). Поэтому следующий оператор использует локальную переменную, а не переменную экземпляра.

Локальная переменная больше не будет содержать значение после возврата метода. Переменная экземпляра не будет изменена.

Подсказка: представьте, что операторы смотрят «вверх» из своего собственного местоположения, чтобы найти каждую из своих переменных. Они могут смотреть за пределы своего «стеклянного ящика» в любом направлении, если им не удается найти переменную внутри собственного метода.

Почти всегда ошибочно использовать одно и то же имя для переменной экземпляра и для локальной переменной. Но это не синтаксическая ошибка, поэтому компилятор вас не предупредит.

как написал @JB Nizet: это дизайнерское решение создателей языка. из-за этого компилятор мог выдает ошибку. и, учитывая сомнительную полезность и склонность к ошибкам этой «функции», может ли она иметь?

Sharon Ben Asher 10.04.2019 08:54

Из раздела JLS Объем декларации:

The scope of a declaration is the region of the program within which the entity declared by the declaration can be referred to using a simple name, provided it is not shadowed.

Из раздела JLS Затенение:

Some declarations may be shadowed in part of their scope by another declaration of the same name, in which case a simple name cannot be used to refer to the declared entity.

Это означает, что вы не можете использовать простое имя (df) для ссылки на переменную уровня класса df, потому что она затенена локальной переменной df. Но есть еще две переменные, и вы можете использовать статическую переменную с именем класса:

public static void main(String[] args){
    System.out.println(fd); //1.0

    double fd = 2.0;

    System.out.println(fd); //2.0
    System.out.println(HelloWorld.fd);
}

Другие вопросы по теме