试图理解最终变量
Trying to understand final variables
最终变量。我已经阅读了我在这个网站和其他网站上能找到的所有内容,我几乎理解了它们,但我仍然有点困惑。
所以,我知道为什么我们将变量声明为 final 的官方答案:它锁定变量并防止它被重新初始化。我的问题是:
如果不能重新初始化,它的值还能变对吧?例如:
final int a = 1;
a = a + 1;
那种代码是否仍然有效,或者 "final int a" 会被永远锁定为 1 的值吗?
如果上面的int a
的值声明为final后仍然可以改变,final的意义何在?
我想问题 2 是我最大的问题。我一直看到所有关于它如何锁定变量的解释,有些人甚至说他们将大部分变量声明为最终变量,但这样做背后的动机对我来说没有意义。
final int a = 1;
a = a + 1;
不,这段代码不会通过编译,因为它试图为最终变量分配一个新值。
但是,如果 a
的类型是某个可变 class 的引用类型,您将能够改变对象的状态。例如:
final StringBuidler a = new StringBuilder (20);
a.append ("foo");
变量的 final
唯一性只会阻止您更改它的值。如果 final 变量引用一个状态可以修改的对象,final
ity 不会阻止您修改该状态。
如果你声明
final int a = 1;
那么以下将导致编译错误,因为您声明为 final 但您正试图为其重新分配一个变量:
a = a + 1;
但是,如果您有一个名为 MyInt 的对象定义如下:
class MyInt{
int myInt = 5;
public int getInt() {
return myInt;
}
public void setInt(int newInt) {
myInt = newInt;
}
}
然后你这样做了:
final MyInt bestIntEver = new MyInt();
你还可以打电话
bestIntEver.setInt(42);
因为对 bestIntEver
的引用没有改变,但是
bestIntEver = new MyInt();
会导致编译错误,因为您正在更改对声明为 final 的变量的引用。
final
表示 a
的值不会改变。但是,根据类型,a
的值实际上可能是一个对象的地址(在问题中它只是一个 int
,所以值不是地址,只是一个 1)。锁定地址 a
并不会锁定对象。将对象设计为 immutable 即可。
最喜欢的比喻是一个公文包,里面有一个 1。一个不可变的设计会锁住公文包,这样人们就无法进入并更改 1。final
会将它戴在你的手腕上,这样人们就不能给你一个新的公文包,里面有其他东西。如果您想确保您的 1 不会发生任何事情,则两者都需要。
但这只适用于对象。
如果您是 primitive(例如 int
),则没有公文包。您没有持有它的句柄(地址)。你只是拿着 1 在你的手上。
如果您是 final
原始人,则 1 已融合到您的手上。你不能放手。你不能拿起任何东西。
Object or primitive,final
的意思是一样的。无论你持有什么,一个地址或一个价值,你都会持有它直到你死去。
If the value of int a above can still be changed even after declaring it as final, what is the point of final?
不能。
...they declare most of their variables as final, but the motivation behind doing so just doesn't make sense to me.
在声明标识符时将其称为变量 final
实际上只是一个常见的坏习惯。如果它是最终的,它就不是可变的。它没有改变。这是一个常数。
创建常量有几个动机。语义正确性是其中之一。 是一个常量 (3.14159...) 所以改变它的值没有意义。另一个动机是防止错误导致错误。变量经常被重用并因此被赋予新的值。保护常量免受意外更改。防止错误代码越多越好。
最终变量。我已经阅读了我在这个网站和其他网站上能找到的所有内容,我几乎理解了它们,但我仍然有点困惑。
所以,我知道为什么我们将变量声明为 final 的官方答案:它锁定变量并防止它被重新初始化。我的问题是:
如果不能重新初始化,它的值还能变对吧?例如:
final int a = 1; a = a + 1;
那种代码是否仍然有效,或者 "final int a" 会被永远锁定为 1 的值吗?
如果上面的
int a
的值声明为final后仍然可以改变,final的意义何在?
我想问题 2 是我最大的问题。我一直看到所有关于它如何锁定变量的解释,有些人甚至说他们将大部分变量声明为最终变量,但这样做背后的动机对我来说没有意义。
final int a = 1;
a = a + 1;
不,这段代码不会通过编译,因为它试图为最终变量分配一个新值。
但是,如果 a
的类型是某个可变 class 的引用类型,您将能够改变对象的状态。例如:
final StringBuidler a = new StringBuilder (20);
a.append ("foo");
变量的 final
唯一性只会阻止您更改它的值。如果 final 变量引用一个状态可以修改的对象,final
ity 不会阻止您修改该状态。
如果你声明
final int a = 1;
那么以下将导致编译错误,因为您声明为 final 但您正试图为其重新分配一个变量:
a = a + 1;
但是,如果您有一个名为 MyInt 的对象定义如下:
class MyInt{
int myInt = 5;
public int getInt() {
return myInt;
}
public void setInt(int newInt) {
myInt = newInt;
}
}
然后你这样做了:
final MyInt bestIntEver = new MyInt();
你还可以打电话
bestIntEver.setInt(42);
因为对 bestIntEver
的引用没有改变,但是
bestIntEver = new MyInt();
会导致编译错误,因为您正在更改对声明为 final 的变量的引用。
final
表示 a
的值不会改变。但是,根据类型,a
的值实际上可能是一个对象的地址(在问题中它只是一个 int
,所以值不是地址,只是一个 1)。锁定地址 a
并不会锁定对象。将对象设计为 immutable 即可。
最喜欢的比喻是一个公文包,里面有一个 1。一个不可变的设计会锁住公文包,这样人们就无法进入并更改 1。final
会将它戴在你的手腕上,这样人们就不能给你一个新的公文包,里面有其他东西。如果您想确保您的 1 不会发生任何事情,则两者都需要。
但这只适用于对象。
如果您是 primitive(例如 int
),则没有公文包。您没有持有它的句柄(地址)。你只是拿着 1 在你的手上。
如果您是 final
原始人,则 1 已融合到您的手上。你不能放手。你不能拿起任何东西。
Object or primitive,final
的意思是一样的。无论你持有什么,一个地址或一个价值,你都会持有它直到你死去。
If the value of int a above can still be changed even after declaring it as final, what is the point of final?
不能。
...they declare most of their variables as final, but the motivation behind doing so just doesn't make sense to me.
在声明标识符时将其称为变量 final
实际上只是一个常见的坏习惯。如果它是最终的,它就不是可变的。它没有改变。这是一个常数。
创建常量有几个动机。语义正确性是其中之一。