在Java中访问静态字段的正确方法是什么?

我刚开始学习Java,我写了一个类来测试使用静态字段。 一切正常但在Eclipse中我看到一个图标,当它hover时出现:“应该以静态方式访问 CarCounter类型的静态方法getCounter。” 什么是正确的方式呢?

这是class级:

public class CarCounter { static int counter = 0; public CarCounter(){ counter++; } public static int getCounter(){ return 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 } } 

静态字段和方法不属于特定对象,而是属于某个类,因此您应该从类中访问它们,而不是从对象访问它们:

 CarCounter.getCounter() 

并不是

 a.getCounter() 

使用CarCounter.getCounter() 。 这清楚地表明它与变量值引用的对象无关 – 计数器与类型本身相关联,而不是与类型的任何特定实例相关联。

这是一个为什么它非常重要的例子:

 Thread t = new Thread(runnable); t.start(); t.sleep(1000); 

代码看起来像什么? 看起来它正在开始一个新线程,然后以某种方式“暂停” – 将其发送到睡眠状态一秒钟。

实际上,它正在启动一个新线程并暂停当前线程,因为Thread.sleep是一个静态方法,它总是让当前线程hibernate。 它不能使任何其他线程睡眠。 当它明确时,它会更加清晰:

 Thread t = new Thread(runnable); t.start(); Thread.sleep(1000); 

基本上,第一段代码编译的能力是语言设计者的一个错误:(

那将是:

 System.out.println(CarCounter.getCounter()); 

静态元素属于该类。 因此,访问它们的最佳方式是通过课程。 所以在你的情况下,打印输出应该是。

 System.out.println(CarCounter.getCounter()); 

这可能会让人觉得不必要,但事实并非如此。 请考虑以下代码

 // 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()); } } 

上面的代码应该打印什么?

上面代码的行为很难定义。 vehicle1被声明为VehicleCounter ,对象实际上是一个VehicleCounter所以它应该打印2(创建两个车辆)。

vehicle2被声明为VehicleCounter但该对象是实际的CarCounter 。 哪个应该打印?

我真的不知道将要打印什么,但我可以看到它很容易混淆。 因此,为了更好的实践,应始终通过它定义的类访问静态元素。

通过以下代码更容易预测要打印的内容。

 // 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()); } } 

希望这能解释。

NawaMan 😀

尽管非常气馁,甚至有可能写下:

 Math m = null; double d = m.sin(m.PI/4.0); System.out.println("This should be close to 0.5 " + (d*d)); 

这是因为静态访问会查看变量的声明类型,并且永远不会实际取消引用它。

应静态访问静态成员,即ClassName.memberName。 虽然允许非静态访问(objectName.memberName)但不鼓励。