为什么要以静态方式访问静态字段?

Ava*_*Ava 57 java static

public enum MyUnits
{
    MILLSECONDS(1, "milliseconds"), SECONDS(2, "seconds"),MINUTES(3,"minutes"), HOURS(4, "hours");

    private MyUnits(int quantity, String units)
    {
        this.quantity = quantity;
        this.units = units;
    }

    private int quantity;
    private  String units;

 public String toString() 
 {
    return (quantity + " " + units);
 }

 public static void main(String[] args) 
 {
    for (MyUnits m : MyUnits.values())
    {
        System.out.println(m.MILLSECONDS);
        System.out.println(m.SECONDS);
        System.out.println(m.MINUTES);
        System.out.println(m.HOURS);
    }
 }
}
Run Code Online (Sandbox Code Playgroud)

这是指post ..wasnt能够回复或评论任何如此创建的新的.为什么是我的

System.out.println(m.MILLSECONDS);
Run Code Online (Sandbox Code Playgroud)

发出警告 - 静态字段MyUnits.MILLSECONDS应该以静态方式访问?谢谢.

Chr*_*son 99

因为当你访问静态字段时,你应该在类上(或者在这种情况下是枚举).如在

MyUnits.MILLISECONDS;
Run Code Online (Sandbox Code Playgroud)

不在实例中

m.MILLISECONDS;
Run Code Online (Sandbox Code Playgroud)

编辑为了解决这个问题,为什么:在Java中,当你声明的东西static,你说,它是类的成员,而不是对象(所以为什么只有一个).因此,在对象上访问它是没有意义的,因为该特定数据成员与该类相关联.

  • 是的......但*为什么*应该以静态方式访问静态字段?! (10认同)

Pet*_*ser 64

实际上有一个很好的理由:
出于含糊不清的原因,非静态访问并不总是有效.

假设我们有两个类,A和B,后者是A的子类,静态字段具有相同的名称:

public class A {
    public static String VALUE = "Aaa";
}

public class B extends A {
    public static String VALUE = "Bbb";
}
Run Code Online (Sandbox Code Playgroud)

直接访问静态变量:

A.VALUE (="Aaa")
B.VALUE (="Bbb")
Run Code Online (Sandbox Code Playgroud)

使用实例进行间接访问(给编译器警告应该静态访问VALUE):

new B().VALUE (="Bbb")
Run Code Online (Sandbox Code Playgroud)

到目前为止,这么好,编译器可以猜出要使用哪个静态变量,超类中的那个静态变量在某种程度上更远,似乎有些合乎逻辑.

现在到了棘手的程度:接口也可以有静态变量.

public interface C {
    public static String VALUE = "Ccc";
}

public interface D {
    public static String VALUE = "Ddd";
}
Run Code Online (Sandbox Code Playgroud)

让我们从B中删除静态变量,并观察以下情况:

  • B implements C, D
  • B extends A implements C
  • B extends A implements C, D
  • B extends A implements C 哪里 A implements D
  • B extends A implements C 哪里 C extends D
  • ...

该语句new B().VALUE现在不明确,因为编译器无法确定哪个静态变量,并将其报告为错误:

错误:对VALUE的引用不明确
C中的变量VALUE和D匹配中的变量VALUE

而这正是静态变量应以静态方式访问的原因.

  • 这应该是IMO的正确答案,它说明了它的危险性. (11认同)
  • @ChrisThompson对"为什么"的回答只是"它没有意义 - 你宣称它是静态的,所以把它当作静态" - 这个答案实际上给了*为什么*这是一个值得具体的坏的坏习惯的理由后果 (4认同)
  • 我同意这个答案比公认的答案更有帮助.所以我并不总是这么做!它仍然很棒.最后,我想随后一个有趣的问题是:为什么首先可以从实例访问静态字段或方法? (4认同)
  • 在这个答案中上面解释的情况最适合这个问题. (2认同)
  • 这更有意义..一个实际的洞察力. (2认同)
  • 很好的答案,但仍然没有说服力:给出的示例并不危险,因为编译器会检测到它。 (2认同)
  • @nyholku:C 和 D 可以是不同库中的接口,这些库最初没有同名的常量,因此 A 可能可以正常编译。较新版本的 C 和 D 可以在不违反约定的情况下各自引入一个同名常量,这将在运行时给 A 带来麻烦,除非它也重新编译。显式引用静态字段(B.VALUE)将解决这个问题,这就是静态字段静态访问的原因。 (2认同)

小智 12

因为......它(MILLISECONDS)是一个静态字段(躲在一个枚举,但它是什么)......但是它被在被调用的情况下给定类型的(见下文,因为这不是真的真的1).

javac将"接受"它,但它应该是MyUnits.MILLISECONDS(或在适用范围内没有前缀).

1实际上,javac将代码"重写"为首选形式 - 如果m恰好是null它在运行时不会抛出NPE - 它实际上从未在实例上调用过).

快乐的编码.


我并没有真正看到问题标题如何适应其余部分:-)更准确和专业的标题增加了问题/答案可能使其他程序员受益的可能性.