I just started learning Java and I wrote a class to test using static fields. Everything works fine but in Eclipse I see an icon which when hovered comes out as: "The static method getCounter from the type CarCounter should be accessed in a static way." What's the right way then?
Here's the class:
public class CarCounter {
static int counter = 0;
public CarCounter(){
counter++;
}
public static int getCounter(){
return counter;
}
}
And here's where I try to access variable counter:
public class CarCounterTest {
public static void main( String args[] ){
CarCounter a = new CarCounter();
System.out.println(a.getCounter()); //This is where the icon is marked
}
}
Static fields and methods are not belong to a specific object, but to a class, so you should access them from the class, and not from an object:
CarCounter.getCounter()
and not
a.getCounter()
Use CarCounter.getCounter()
. That makes it clear that it's nothing to do with the object that the a
variable's value refers to - the counter is associated with the type itself, rather than any specific instance of the type.
Here's an example of why it's really important:
Thread t = new Thread(runnable);
t.start();
t.sleep(1000);
What does it look like that code is doing? It looks like it's starting a new thread and then "pausing" it somehow - sending it to sleep for a second.
In fact, it's starting a new thread and pausing the current thread, because Thread.sleep
is a static method which always makes the current thread sleep. It can't make any other thread sleep. That's a lot clearer when it's explicit:
Thread t = new Thread(runnable);
t.start();
Thread.sleep(1000);
Basically, the ability of the first snippet of code to compile is a mistake on the part of the language designers :(
That would be:
System.out.println(CarCounter.getCounter());
It is even possible, though highly discouraged, to write:
Math m = null;
double d = m.sin(m.PI/4.0);
System.out.println("This should be close to 0.5 " + (d*d));
This is because static accesses look at the declared type of the variable, and never actually dereference it.
Static elements belong to the class. Therefore, the best way to access them is via the class.
So in your case, the print out should be.
System.out.println(CarCounter.getCounter());
This may feel triviaval unnecessary but it is not.
Consider the following code
// VehicleCounter.java
public class VehicleCounter {
static int counter = 0;
public VehicleCounter(){
counter++;
}
public static int getCounter(){
return counter;
}
}
// CarCounter.java
public class CarCounter extends VehicleCounter {
static int counter = 0;
public CarCounter(){
counter++;
}
public static int getCounter(){
return counter;
}
}
// CarCounterTest.java
public class CarCounterTest {
public static void main( String args[] ){
VehicleCounter vehicle1 = new VehicleCounter();
VehicleCounter vehicle2 = new CarCounter();
System.out.println(vehicle1.getCounter());
System.out.println(vehicle2.getCounter());
}
}
What should the above code prints?
The behaviour of the above code is hard to define. vehicle1
is declared as VehicleCounter
and the object is actually a VehicleCounter
so it should print 2 (two vehicles are created).
vehicle2
is declared as VehicleCounter
but the object is actuall CarCounter
. Which should be printed?
I really don't know what will be printed but I can see that it can easily be confused. So for a better practice the static elements should always be accessed via the class it defined.
It much easier to predict what to be printed by the following code.
// CarCounterTest.java
public class CarCounterTest {
public static void main( String args[] ){
VehicleCounter vehicle1 = new VehicleCounter();
VehicleCounter vehicle2 = new CarCounter();
System.out.println(VehicleCounter.getCounter());
System.out.println(CarCounter .getCounter());
}
}
Hope this explains.
NawaMan :-D
Static members should be accessed statically, i.e., ClassName.memberName.
Non-static access is allowed though (objectName.memberName) but is discouraged.