为什么我可以在Java中成功地在main()内声明一个静态字段?

问题描述 投票:0回答:3

我宣布了private static double fd,然后我再次在main()内宣布double fd。为什么我可以成功编译并运行它?

    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


    }
}
java static field
3个回答
0
投票

这不是语法错误(虽然它可能会导致逻辑错误,一个错误)。编译器将编译此代码而不会抱怨。 double fd的第二个声明为main方法创建一个局部变量。此变量的范围以其声明开始,并在块的结尾处结束(与所有局部变量一样)。所以下一个语句使用局部变量,而不是实例变量。

方法返回后,局部变量将不再保留值。实例变量不会被更改。

提示:将语句看作从他们自己的位置向上看,以找到他们的每个变量。如果他们未能在自己的方法中找到变量,他们可以向任何方向看他们的“玻璃盒子”。

对实例变量和局部变量使用相同的名称几乎总是错误的。但它不是语法错误,因此编译器不会警告您。


1
投票

来自JLS Scope of a Declaration部分:

声明的范围是程序的区域,声明声明的实体可以使用简单的名称引用该区域,前提是它没有被遮蔽。

来自JLS Shadowing部分:

某些声明可能会在其作用域的一部分中被另一个同名声明所遮蔽,在这种情况下,简单名称不能用于引用声明的实体。

这意味着您不能使用简单名称(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);
}

0
投票

变量fd是函数作用域,想想它,编译器首先检查离它最近的范围,然后如果它找到那里它试图检查全局范围,如果它在本地范围内找到了什么,它将打印出来,或者否则继续检查其他范围。

© www.soinside.com 2019 - 2024. All rights reserved.