Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么对象可以更改类变量的值?_Java - Fatal编程技术网

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

Java 为什么对象可以更改类变量的值?,java,Java,根据甲骨文的 有时,您希望拥有对所有对象通用的变量。这是通过“静态”修改器完成的。声明中包含静态修饰符的字段称为静态字段或类变量。它们与类相关联,而不是与任何对象相关联。类的每个实例都共享一个类变量,该变量位于内存中的一个固定位置 根据这个定义,可以安全地推断静态变量属于该类,并且该类的任何对象都不能访问该静态变量进行修改。因为所有对象都共享该静态变量 因此,同一定义中的这一行有点令人困惑: 任何对象都可以更改类变量的值 因此,我尝试了这段代码,它打印了45条(尽管我收到一条警告说“通过实例引用

根据甲骨文的

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

根据这个定义,可以安全地推断静态变量属于该类,并且该类的任何对象都不能访问该静态变量进行修改。因为所有对象都共享该静态变量

因此,同一定义中的这一行有点令人困惑:

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

因此,我尝试了这段代码,它打印了45条(尽管我收到一条警告说“通过实例引用访问静态成员”):

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

根据这个定义,可以安全地推断静态变量属于该类,并且该类的任何对象都不能访问该静态变量进行修改。因为所有对象都共享该静态变量

否。根据此定义,该静态变量属于该类,并且可由该类的任何实例修改。这并不意味着当某个变量被共享时,它就不应该被修改。如果需要,请使用
final

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

例如,在构造函数中增加值,在终结器中减少值。

这并不是“一个对象”可以做到的,只是您在代码中可以访问该变量,不幸的是,Java允许您访问静态成员(变量和方法),就好像它们是实例成员一样。这最终会产生非常误导性的代码,例如

Thread t = new Thread(...);
t.start();
t.sleep(1000);
最后一行看起来像是要求新启动的线程睡眠,但实际上它会使当前线程睡眠

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

Thread.sleep(1000);
还是你的情况

Main.value = 45;
(我相信在旧版本的Java中,它会发出代码,用“通过”访问静态成员的变量检查空值,但它甚至不再这样做了。)

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

根据此定义,可以安全地推断静态变量属于该类,不应被该类的任何对象访问以进行修改,因为所有对象都共享它

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


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

Main.value = 45;

静态变量对于定义它的整个类只有一个实例。创建实例时,不会创建该静态变量的实例。只有一个,并且可以由任何函数自由修改,而无需实例。(除非声明为final)

能够使用
静态
变量和方法创建一个类,以便从该类创建的所有实例或对象共享这些变量和方法非常有用,请参阅

在类中的多个实例或从该类创建的对象之间共享类中的
静态
变量时,可能需要使用
同步
修饰符,以确保如果多个线程中的对象正在修改
静态
变量,则保持数据完整性,请参阅和另请参阅

final
关键字see用于确定变量是否不可变。因此,如果希望类
静态
变量应为不可变或常量,则可以将
最终
修饰符添加到定义中。但是,请看这一点,它解释了引用的基础值在函数式编程的意义上可能不是不变的。另见

您还可以使用诸如
public
之类的修饰符来确定类中变量和方法的可见性,请参见


通过使用诸如
final
private
之类的修饰符,程序员能够微调类中变量和从类实例化的对象的可见性和可修改性。

列举编译器如何将对象字段访问更改为类字段访问的示例

public class A {
    static int foo = 25;

    static public void main(String[] arg){
        B b = new B();
        A a = b;

        System.out.println(b.foo);
        System.out.println(a.foo);
    }
}

class B extends A {
    static int foo = 60;
}
输出为:

60
25

它还表明,由于它与对象字段具有不同的行为,因此可以使用

我不知道你为什么认为这不应该被允许。这完全取决于你和你的设计。我可以想到实例对象可能改变静态变量值的例子。然而,从关注点分离的角度来看,这并不是一个好的实践。可以安全地推断,静态变量属于类,并且不应该被类的任何对象访问以进行修改:不,它不是。这是你的解释,但不是语言的定义。房子是所有住在房子里的人共用的。为什么这会阻止住在房子里的人修改房子?
不,只要访问修饰符允许,静态字段就可以进行修改。
这很有帮助。你知道为什么Java是这样设计的吗?C++的历史遗产?@LucaCremonesi:不幸的是,不知道。
public class A {
    static int foo = 25;

    static public void main(String[] arg){
        B b = new B();
        A a = b;

        System.out.println(b.foo);
        System.out.println(a.foo);
    }
}

class B extends A {
    static int foo = 60;
}
60
25