为什么对象可以更改类变量的值?

ojo*_*ifu 1 java

根据Oracle的定义,

有时,您希望拥有所有对象共有的变量.这是通过静态修改器完成的.在声明中具有static修饰符的字段称为静态字段或类变量.它们与类相关联,而不是与任何对象相关联.该类的每个实例共享一个类变量,该变量位于内存中的一个固定位置.

通过这个定义,可以安全地推断出一个静态变量属于该类,并且不应该被类的任何对象访问以进行修改.因为所有对象都共享它.

所以来自同一定义的这一行有点令人困惑:

任何对象都可以改变类变量的值......

所以我尝试了这个代码并打印出45(尽管我收到警告说"通过实例引用访问静态成员"):

public class Main {

static int value = 8;

public static void main(String[] args) {
// write your code here

    Main main = new Main();

    main.value = 45;

    System.out.println(value);
  }
}
Run Code Online (Sandbox Code Playgroud)

如果这是一个Student类,并且我有一个静态变量numberOfStudents,为什么要允许该类的一个对象更改此类变量的值?

Jon*_*eet 9

实际上并不是"一个对象"可以 - 只是你在代码中可以访问该变量,不幸的是,Java允许您访问静态成员(包括变量和方法),就好像它们是实例成员一样.这最终会带来非常误导性的代码,例如

Thread t = new Thread(...);
t.start();
t.sleep(1000);
Run Code Online (Sandbox Code Playgroud)

最后一行看起来像是要求新启动的线程休眠 - 但实际上它会使当前线程休眠.

这基本上是Java中的一个缺陷.编译器会默默地将这样的代码转换为

Thread.sleep(1000);
Run Code Online (Sandbox Code Playgroud)

或者在你的情况下

Main.value = 45;
Run Code Online (Sandbox Code Playgroud)

(我相信在Java的旧版本中,它会发出代码,通过您访问静态成员"through"的变量检查无效,但它甚至不再这样做了.)

许多IDE将允许您使用警告或错误标记此类代码.我鼓励你打开这样一个功能.如果您看到类似的现有代码,请将其更改为使用通过声明类直接访问静态成员,因此很清楚发生了什么.


Eng*_*uad 5

通过这个定义,可以安全地推断出一个静态变量属于该类,并且不应该被该类的任何对象修改.因为所有对象都共享它.

不,只要访问修饰符允许,静态字段就可以进行修改.


main.value = 45;
Run Code Online (Sandbox Code Playgroud)

编译器将在编译时读取此行,如下所示:

Main.value = 45;
Run Code Online (Sandbox Code Playgroud)