What is the proper way of accessing static fields

2020-01-29 17:52发布

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
    }
}

6条回答
够拽才男人
2楼-- · 2020-01-29 18:00

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 :(

查看更多
萌系小妹纸
3楼-- · 2020-01-29 18:04

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.

查看更多
倾城 Initia
4楼-- · 2020-01-29 18:05

Static members should be accessed statically, i.e., ClassName.memberName. Non-static access is allowed though (objectName.memberName) but is discouraged.

查看更多
地球回转人心会变
5楼-- · 2020-01-29 18:16

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()
查看更多
手持菜刀,她持情操
6楼-- · 2020-01-29 18:20

That would be:

System.out.println(CarCounter.getCounter());
查看更多
beautiful°
7楼-- · 2020-01-29 18:23

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

查看更多
登录 后发表回答