最近有人问了我这个问题。但是我无法简洁地解释这两个概念的区别。
例如:
Final 和 Immutable:
final String name = "John";
如果现在我写下:
name = "Sam";
我将会得到编译错误。
不可变:
String name = "John";
name = "Sam";
它有效。
我认为这解释了其中的一部分应用。但是我可以得到一个易于理解的关于这两个主题的解释吗?
最近有人问了我这个问题。但是我无法简洁地解释这两个概念的区别。
例如:
Final 和 Immutable:
final String name = "John";
如果现在我写下:
name = "Sam";
我将会得到编译错误。
不可变:
String name = "John";
name = "Sam";
它有效。
我认为这解释了其中的一部分应用。但是我可以得到一个易于理解的关于这两个主题的解释吗?
final
表示你不能改变对象的引用指向另一个引用或其他对象,但是你仍然可以修改它的状态(使用 setter 方法)。而 immutable 表示对象的实际值不能被更改,但是你可以将其引用指向另一个对象。String
对象,并将 name
引用指向它。final
保证对象的地址不会改变,而Immutable
则表示一旦创建了对象,就无法更改其状态。
final
只是一个关键字,而Immutable
是一种模式。
对于您的第一个问题,您将变量标记为
final
,这意味着您将无法更改其内存地址,并且不能再次赋值。在第二个问题中,
Immutable
确保您无法更改所创建的对象的状态。
final
时,引用不会更改。它将始终指向同一个对象。immutable
,则可以使用其上的方法来更改对象本身 - 它是相同的对象,但其属性已更改。final关键字表示对象不可更改。
final String s = "Hello";
// Not allowed.
s = "Bye";
对象的内容不能被改变。
BigInteger one = BigInteger.ONE;
// Does not change `one` or `BigInteger.ONE`.
one.add(BigInteger.ONE);
// Have to do it this way.
BigInteger two = one.add(one);
final String name = "John";
name
总是指向相同的内存位置。现在为什么我说内存位置呢?因为引用所指向的对象可能是可变的,比如整数数组或列表。所以如果我说 final int[] arr = {5,6,1};
,我可以执行 arr[2] = 3;
,但我不能执行 arr = {3,4,5}
,因为您将尝试将新的 int[]
分配给 final 变量 arr
,这是一个新的内存位置,编译器会显示错误。"最初的回答"String name = "John";
name = "Sam";
name
变量是一个 String
类型的变量,由于在 Java 中,String
是不可变的(immutable),这意味着一旦创建了对象,并且即使您将其更改为 Sam
,它也是一个不同的对象,被引用的对象 name
的状态无法更改。之前的对象 John
将没有引用,并且如果没有其他指向它的引用,则可以在垃圾收集器运行时进行收集。public class test {
public static void main(String[] args) {
final A aObject = new A();
System.out.println("Old value :" + aObject.a);
aObject.a = 2;
System.out.println("New value :" + aObject.a);
}}
class A {
public int a = 1;}
Immutable指的是一旦对象的构造函数执行完成,该实例就无法被更改。
这很有用,因为它意味着您可以传递对该对象的引用,而不必担心其他人会更改其内容。特别是在处理并发时,从不更改的对象没有锁定问题。
例如:
class Foo
{
private final String myvar;
public Foo(final String initialValue)
{
this.myvar = initialValue;
}
public String getValue()
{
return this.myvar;
}
}
Foo不必担心调用getValue()的调用者可能会更改字符串中的文本。
如果您想象一个类似于Foo的类,但其成员是StringBuilder而不是String,则可以看到调用getValue()的调用者将能够更改Foo实例的StringBuilder属性。
final是Java中的保留关键字,用于限制用户,可以应用于成员变量、方法、类和局部变量。在Java中,Final变量通常使用static关键字声明,并被视为常量。例如:
public static final String hello = "Hello"; 当我们在变量声明中使用final关键字时,存储在该变量中的值不能在后面更改。
例如:
public class ClassDemo {
private final int var1 = 3;
public ClassDemo() {
...
}
}
不可变性:String和包装类是不可变的。由于String常量池,它们不能在对象内部更改其值,但可以更改持有不同值的对象的引用。
String s1 = new String("cant't change");
最终结果:当我们创建一个字符串的引用时
Final String s2 = "cant't change";
s2
的引用指向一个内部值为“无法更改”的对象。
现在,引用s将始终指向保存值“无法更改”的对象。它的引用不能被更改。