0
public class Knowing {

    static final long tooth = 343L;

    static long doIT(long tooth) {
        System.out.print(++tooth + " ");
        return ++tooth;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        System.out.print(tooth + " ");
        final long tooth = 340L;

        new Knowing().doIT(tooth);
        System.out.println(tooth);
    }
}

好的,这是我的问题:

  • 如果我们声明了一个全局变量static final long tooth = 343L;我们如何在主方法中声明另一个变量final long tooth = 340L;我只想知道为什么允许这样做,因为我运行了它并且没有错误?

  • 而且不应该通过使用className.variableName而不是通过创建新的instance.variable名称来访问全局静态变量tooth,为什么只允许一个警告?

4

5 回答 5

7

我们如何才能在 main 方法中声明 final long 牙 = 340L; 中的另一个变量;

因为语言规范说你可以。从JLS 的第 6.4.1 节,关于阴影

一个名为 n 的局部变量或异常参数的声明 d 在 d 的范围内隐藏,(a) 任何其他名为 n 的字段的声明在 d 出现点的范围内,以及 (b) 任何其他名为 n 的变量在 d 出现的点的范围内,但未在声明 d 的最内层类中声明。

你应该这样做吗?很少。另一方面,我也很少看到它是一个问题。

对于你的第二个问题:

而且不应该通过使用className.variableName而不是通过创建新的instance.variable名称来访问全局静态变量tooth,为什么只允许一个警告?

这是Java,IMO中的设计缺陷。甚至警告也不是语言规范的一部分。您应该始终避免这样做,因为它会使代码做一些看起来不像正在做的事情。我通常举的例子是:

Thread backgroundThread = new Thread(someRunnable);
backgroundThread.start();
backgroundThread.sleep(1000);

这使得执行线程休眠,而不是新线程。

于 2012-06-12T18:19:22.153 回答
2

局部变量使全局黯然失色。但是您仍然可以通过使用 classname.variable 来访问全局。

于 2012-06-12T18:17:59.250 回答
1

toothin 变量是局部变量,main优先于全局变量。如果你想访问全局的,你应该如下引用它this.tooth

如果您想了解更多关于变量和范围的信息,我建议您阅读Oracle 文档。

于 2012-06-12T18:18:53.670 回答
1

参数/变量隐藏是语言设计中的常见特征。例如,第三方库中的方法的客户端无法控制该库用于形式参数的名称。语言设计的另一个常见做法是一致性。这意味着在任何可以声明变量的地方,都可以在外部范围内隐藏同名变量。请注意,如果您尝试声明与同一范围内的变量同名的局部变量,您将收到编译器错误。

使用 Builder 模式时,静态变量的非静态访问是一个方便的特性。但是,它具有欺骗性(正如另一个答案以图形方式展示的那样),因此编译器将其标记为警告。

于 2012-06-12T18:21:03.263 回答
1

首先className.variableName is a legal way of accessing a static member, but its possible to create an instance of the class which has the static member,访问那个静态成员。将此视为错误或缺陷,在诸如 Math 之类的类中变得不可能,其中构造函数是私有的,而且该类中没有实例变量,因此创建对象毫无用处。对于范围的事情,请查看此链接 http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.4.1

于 2012-06-12T18:25:42.683 回答