2011-04-12 103 views
48
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); 
    } 
} 
} 

这是指post ..无法回复或评论任何如此创建一个新的。为什么我的为什么要以静态方式访问静态字段?

System.out.println(m.MILLSECONDS); 

给予警告,静态场MyUnits.MILLSECONDS应以静态的方式来访问? 谢谢。

+7

我改变了标题,这是“Java代码优化”。请多关心问题标题。 – 2011-04-12 23:48:41

+0

雅我的坏,从下次会照顾:) – Ava 2011-04-12 23:56:51

回答

84

因为当你访问一个静态字段时,你应该在类上(或者在这个例子中是enum)这样做。作为

MyUnits.MILLISECONDS; 

不上实例作为

m.MILLISECONDS; 

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

+0

非常感谢!得到它了。 – Ava 2011-04-12 23:54:16

+7

是......但是为什么*应该静态访问静态字段?! – dokaspar 2012-07-31 08:34:33

+0

@Dominik检查我的编辑 – 2012-10-15 16:35:01

10

因为......它(MILLISECONDS)是一个静态字段(躲在一个枚举,但它是什么)......但是它被在一个实例给定类型的调用(见下文为这不是真的真)。 javac将“接受”,但它应该确实是MyUnits.MILLISECONDS(或者在适用范围中没有前缀)。

其实,javac的“重写”的代码,以优选的形式 - 如果m正好是null不会扔在运行时的NPE - 这是从来没有真正于实例调用)。

快乐编码。


我真的不看到问题的标题如何与其他:-)更精确和专业职称增加可能引擎盖问题符合中/答案可以受益其他程序员。

48

实际上,有一个很好的理由:
非静态访问并不总是工作,歧义的原因。

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

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

public class B extends A { 
    public static String VALUE = "Bbb"; 
} 

直接访问静态变量:

A.VALUE (="Aaa") 
B.VALUE (="Bbb") 

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

new B().VALUE (="Bbb") 

到目前为止,编译器可以猜测使用哪个静态变量,超类中的那个变得更远,似乎有点合乎逻辑。

现在到了棘手的地步:接口也可以有静态变量。

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

public interface D { 
    public static String VALUE = "Ddd"; 
} 

让我们从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现在暧昧,为编译器不能决定哪些静态变量是指。这正是静态变量应该以静态方式访问的原因。

+8

这应该是IMO的正确答案,它显示了它为什么危险。 – Water 2015-04-05 23:23:54

+3

@ChrisThompson对“为什么”的回答只是“它没有任何意义 - 你宣称它是静态的,所以把它当作静态的” - 这个答案实际上给了*理由为什么*这是一个不好的做法,值得一个具体的坏结果 – mmcrae 2015-04-15 22:28:02

+3

我同意这个答案比接受的更有帮助。 SO并不总是像我想的那样工作!尽管如此,它仍然很棒。最后,我想接下来一个有趣的问题是:为什么有可能首先从实例中访问静态字段或方法? – Dici 2015-09-21 22:53:26

相关问题