通过Oracle的definition,
有时,您希望拥有所有对象共有的变量。这是通过静态修改器完成的。在声明中具有static修饰符的字段称为静态字段或类变量。它们与类相关联,而不是与任何对象相关联。该类的每个实例共享一个类变量,该变量位于内存中的一个固定位置。
通过这个定义,可以安全地推断静态变量属于类,并且不应该被类的任何对象访问以进行修改。因为所有对象都共享它。
因此来自同一定义的这一行有点令人困惑:
任何对象都可以更改类变量的值......
所以我尝试了这段代码并打印出45(虽然我收到警告说"静态成员通过实例引用&#34访问;):
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);
}
}
如果这是Student
类,并且我有一个名为numberOfStudents
的静态变量,为什么要允许该类的一个对象更改此类变量的值?
答案 0 :(得分:9)
可以 - 它只是你可以访问该变量的代码,不幸的是,Java允许你访问静态成员(包括变量和方法),就好像它们是实例成员一样。最终会产生非常误导性的代码,例如
Thread t = new Thread(...);
t.start();
t.sleep(1000);
最后一行看起来就像它要求新启动的线程休眠一样 - 但实际它会使当前线程休眠。< / p>
这基本上是Java中的一个缺陷。编译器会默默地将代码转换为
Thread.sleep(1000);
或在你的情况下
Main.value = 45;
(我相信在Java的旧版本中,它会发出使用您访问静态成员的变量检查无效的代码&#34;通过&#34;,但它甚至不会这样做更多。)
许多IDE允许您使用警告或错误标记此类代码。我鼓励你打开这样一个功能。如果您看到类似的现有代码,请将其更改为使用通过声明类直接访问静态成员,这样就可以清楚发生了什么。
答案 1 :(得分:5)
通过这个定义,可以安全地推断出一个静态变量属于该类,并且不应该被类的任何对象访问以进行修改。因为所有对象都共享它。
不,只要访问修饰符允许,静态字段就可以进行修改。
main.value = 45;
编译器将在编译时将此行读取为:
Main.value = 45;
答案 2 :(得分:3)
能够使用static
变量和方法创建一个类,以便从类创建的所有实例或对象共享这些变量和方法非常有用,请参阅When to use static methods。
在从类创建的多个实例或对象之间共享类中的static
变量时,可能需要synchronized
修饰符,以确保static
变量正在由多个线程中的对象修改,维护数据完整性,请参阅What does synchronized mean?并查看How to synchronize a static variable among threads running different instances of a class in java。
final
关键字,请参阅How final keyword works用于确定变量是否是不可变的。因此,如果您想要一个应该是不可变的类static
变量或常量,那么您可以将final
修饰符添加到定义中。但是请参阅Java final keyword for variables,它解释了在函数式编程意味着的意义上,引用的基础值可能不是不可变的。另请参阅what is meant by immutable以及Why final keyword is necessary for immutable class。
您还可以使用public
等修饰符来确定类中变量和方法的可见性,请参阅What does public static void mean in Java。
通过使用final
或private
等修饰符,程序员可以精确调整类中实例中变量的可见性和可修改性。
答案 3 :(得分:2)
Litle示例编译器如何将对象字段访问权限更改为类字段访问。
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
它还表明,由于它具有与对象字段不同的行为,因此可能会令人困惑。
答案 4 :(得分:0)
通过这个定义,可以安全地推断静态变量属于类,并且不应该被类的任何对象访问以进行修改。因为所有对象都共享它。
没有。根据这个定义,该静态变量属于该类, 可由该类的任何实例修改。没有任何暗示,当共享某个变量时,它不应该是可修改的。如果您愿意,请使用final
。
如果这是
Student
类,并且我有一个名为numberOfStudents
的静态变量,为什么要允许该类的一个对象更改此类变量的值?
例如,在构造函数中递增值并在终结器中递减它。
答案 5 :(得分:0)
静态变量具有定义它的整个类的单个实例。创建实例时,该静态变量的实例不会创建。只有一个,并且可以通过任何函数自由修改,而无需实例。 (除非它被宣布为最终)