Java中的final和static

25

我在一本书中读到了这个句子,但我不太理解:

既是静态的又是最终的字段只有一个不可更改的存储空间。

可以有人为我解释一下吗?


请注意,final还有并发实现。final字段在某种程度上保证了线程安全性,而其他字段则没有。查看:我的答案在这里:https://dev59.com/DFHTa4cB1Zd3GeqPP0T3#3974372 - andersoj
4个回答

52
你感到困惑的原因可能是英语中的“static”一词和它在Java中的含义只有松散的关联。
以“正常”方式在类 Cat 中定义的变量可以称为实例变量。
class Cat {
   int weight;
}
每次创建 Cat 类型的新对象时,都会创建变量“weight”的新副本。如果创建 10 个 Cat 对象,则每个对象都有自己的 weight 变量副本。
可以将“静态”变量视为类级别变量,而不是实例变量。静态变量只有一个副本,属于 Cat 类本身,而不是每个 Cat 对象都有一个副本。
class Cat {
   static String speciesName;

   int weight;
}

无论我们创建多少个Cat类型的对象,这里只有一个speciesName的副本。

如果静态变量也是“final”的话,那么这个变量的唯一一个副本是唯一不能被更改的存储空间。如果在上面的例子中变量'weight'是final的,那么将会有10个不能被更改的存储空间,对应于我们创建的每个Cat类型的对象。


我知道这已经过时了,但我只是想说,这绝对是最简单易懂的解释,真的帮助我理解了这个问题。+1 - Script47
非常好地解释了静态变量与普通变量的区别。谢谢。 - Arpit Patel

26

static变量对于类的所有实例都是共同的。final变量在第一次设置后无法更改。

因此,在Java中,static final变量对于类的所有实例都是共同的,并且在第一次设置后无法更改。

class Car {

    static final int numberOfWheels = 4;
    Color color;

    public Car(Color color) {
        this.color = color;
    }
}

Car redCar = new Car(Red);
Car blueCar = new Car(Blue);

每辆车现在都拥有一个独立的且可变的属性color,它们共享属性numberOfWheels,但这个属性是不可更改的。


2
@Jonas:我不太敢称final变量为“常量”,因为这个术语通常用于编译时变量或在声明时分配的变量。相反,我会将final变量描述为只能被赋值一次的变量(对于类成员来说,这需要在构造函数中完成赋值)。 - Brian
2
@Brian,我没有看到原始措辞,但是Java中的final变量很像常量。它们编译成代码的方式就像#define一样,并且由此产生了一些有趣的副作用(例如更改#define并重新编译该类只会更新其他类中的值-它们将具有编译的原始值)。您对“常量”的不同定义是什么? - Bill K
@Bill K:很有趣,我不知道这一点。Oracle/Sun在Java教程中也将类变量称为常量 - Jonas
@Bill K:我同意static final变量实际上是一个常量。然而,Jonas的回答最初的措辞将final变量称为常量,我认为这不是一个准确的措辞选择,因为类的不同实例可以有不同的final变量值。 - Brian
@Jonas:static final 基本上是一个常量,就像你提供的链接所示。然而,单独使用 finalstatic 并不会创建一个常量变量。 - Brian
1
@Jonas 实际上,你引用的那个页面非常准确。它并没有说类变量是常量,而是关于常量的内容是:“静态修饰符与 final 修饰符结合使用,也用于定义常量。” 并且进一步区分了传统的“编译时”常量和在运行时计算一次的常量。 - Bill K

1
  • Final 的意思是不能重新给任何变量赋值。
  • Static 的意思是在整个类的所有方法中只能有一个引用副本。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接