72
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);
    }
 }
}

This is referring to post ..wasnt able to reply or comment to any so created a new one. Why are my

System.out.println(m.MILLSECONDS);

giving warnings-The static field MyUnits.MILLSECONDS should be accessed in a static way ? Thanks.

Community
  • 1
  • 1
Ava
  • 5,783
  • 27
  • 58
  • 86

3 Answers3

116

Because when you access a static field, you should do so on the class (or in this case the enum). As in

MyUnits.MILLISECONDS;

Not on an instance as in

m.MILLISECONDS;

Edit To address the question of why: In Java, when you declare something as static, you are saying that it is a member of the class, not the object (hence why there is only one). Therefore it doesn't make sense to access it on the object, because that particular data member is associated with the class.

Chris Thompson
  • 35,167
  • 12
  • 80
  • 109
  • 12
    Yes... but *WHY* should the static field be accessed in a static way?! – dokaspar Jul 31 '12 at 08:34
  • 1
    That's a problem in case the class i'm using takes a role of importance in the static method. In case i'm using new Object().getClass().getEnclosingClass(); – Seby Oct 03 '13 at 08:06
  • but members of the class are also objects no?! – sivi Jul 16 '15 at 10:21
83

There's actually a good reason:
The non-static access does not always work, for reasons of ambiguity.

Suppose we have two classes, A and B, the latter being a subclass of A, with static fields with the same name:

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

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

Direct access to the static variable:

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

Indirect access using an instance (gives a compiler warning that VALUE should be statically accessed):

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

So far, so good, the compiler can guess which static variable to use, the one on the superclass is somehow farther away, seems somehow logical.

Now to the point where it gets tricky: Interfaces can also have static variables.

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

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

Let's remove the static variable from B, and observe following situations:

  • B implements C, D
  • B extends A implements C
  • B extends A implements C, D
  • B extends A implements C where A implements D
  • B extends A implements C where C extends D
  • ...

The statement new B().VALUE is now ambiguous, as the compiler cannot decide which static variable was meant, and will report it as an error:

error: reference to VALUE is ambiguous
both variable VALUE in C and variable VALUE in D match

And that's exactly the reason why static variables should be accessed in a static way.

Peter Walser
  • 15,208
  • 4
  • 51
  • 78
  • 13
    This should be the correct answer IMO, it shows why its dangerous. – Water Apr 05 '15 at 23:23
  • 5
    @ChrisThompson 's answer to "why" was just "it doesn't make sense -- you declared it static, so use it as static" -- THIS answer actually gives justification for *why* it's a bad practice worth a concrete bad consequence – Don Cheadle Apr 15 '15 at 22:28
  • 4
    I agree this answer is much more helpful than the accepted one. SO does not always work as it should I guess ! It's still great though. Finally, I guess a subsequent interesting question is : why is it possible to access static fields or methods from instances in the first place ? – Dici Sep 21 '15 at 22:53
  • 2
    The situation explained above in this answer is best fit to the question. – Preetam Kumar Sep 01 '16 at 07:39
  • 2
    this make more sense.. an actual insight. – Saif Sep 07 '16 at 06:08
  • 2
    Good answer, but still not convincing: the example given is not dangerous because the compiler detects it. – nyholku Oct 22 '17 at 05:45
  • 1
    @nyholku: C and D can be interfaces in differnt libraries, which initially do not have a constant with the same name, so A might compile fine. Newer versions of C and D can each introduce a constant with the same name without breaking the contract, which will cause trouble for A at runtime, unless it's recompiled as well. Making references to static fields explicit (B.VALUE) will solve this, hence the reasoning for static access of static fields. – Peter Walser Sep 15 '19 at 17:35
  • 1
    @PeterWalser thanks. Interesting scenario! I could argue that in java language there are no libraries concept and thus in theory this could not occur but I won't do that as separate compilation is a fact. I'm almost convinced. :) – nyholku Sep 17 '19 at 03:34
12

Because ... it (MILLISECONDS) is a static field (hiding in an enumeration, but that's what it is) ... however it is being invoked upon an instance of the given type (but see below as this isn't really true1).

javac will "accept" that, but it should really be MyUnits.MILLISECONDS (or non-prefixed in the applicable scope).

1 Actually, javac "rewrites" the code to the preferred form -- if m happened to be null it would not throw an NPE at run-time -- it is never actually invoked upon the instance).

Happy coding.


I'm not really seeing how the question title fits in with the rest :-) More accurate and specialized titles increase the likely hood the question/answers can benefit other programmers.