简体   繁体   English

java中的immutable和final有什么区别?

[英]What is the difference between immutable and final in java?

I was recently asked this quesion. 我最近被问到这个问题。 But was not able to explain concisely what exactly sets both these concepts apart. 但是无法简明扼要地解释这两个概念的确切区别。

For example 例如

Final and Immutable: 最终和永恒:

final String name = "John";

if I now write 如果我现在写

name = "Sam";

I will get a compiler error 我会得到一个编译器错误

Immutable: 一成不变的:

String name = "John";
name = "Sam"; 

it works. 有用。

I think this explains a part of it in application. 我认为这解释了它在应用中的一部分。 But can I get a good, easy to understand explanation on both these topic? 但是,我可以对这两个主题得到一个好的,易于理解的解释吗?

final means that you can't change the object's reference to point to another reference or another object , but you can still mutate its state (using setter methods eg). final表示您不能将对象的引用更改为指向另一个引用或另一个对象 ,但您仍然可以改变其状态(例如使用setter方法)。 Where immutable means that the object's actual value can't be changed, but you can change its reference to another one. 其中immutable意味着对象的实际值无法更改,但您可以将其引用更改为另一个。

Concerning the second part of your question (immutability part), the compiler creates a new String object with the value of "Sam", and points the name reference to it. 关于问题的第二部分(不变性部分),编译器创建一个值为“Sam”的新String对象,并将name引用指向它。

final ensure that the address of the object remains the same. final确保对象的地址保持不变。 Where as the Immutable suggests that we can't change the state of the object once created. Immutable表示我们无法在创建后更改对象的状态。

final is just a keyword whereas Immutable is a pattern. final只是一个关键字,而Immutable是一个模式。

In Case of your first question you have marked the variable as final , which means you would not be able to change the memory address of it and can't assign a value once more. 在第一个问题的情况下,您已将变量标记为final ,这意味着您将无法更改其内存地址,并且无法再次分配值。

In case of your second question Immutable ensures you can't change the state of the object you have created. 如果你的第二个问题, Immutable确保你不能改变你创建的对象的状态。

final 最后

The object cannot be changed. 对象无法更改。

final String s = "Hello";
// Not allowed.
s = "Bye";

immutable 一成不变

The contents of the object cannot be changed. 对象的内容无法更改。

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);

When you have a field declared as final , the reference will not change . 如果您将字段声明为final则引用不会更改 It will always point at the same Object. 它总是指向同一个对象。

if the Object is not immutable , the methods on it can be used to change the Object itself - it is the same Object, but its properties have been changed . 如果Object不是immutable ,它上面的方法可用于更改Object本身 - 它是相同的Object,但其属性已被更改

Immutable: 一成不变的: http://www.programcreek.com/2009/02/diagram-to-show-java-strings-immutability/

when you change the String, create new String object ('abcdef') and change the reference from 'abce' to 'abcdef' .But you can not remove 'abcd' . 当你更改String时,创建新的String对象('abcdef')并将引用从'abce'更改为'abcdef' 。但是你不能删除'abcd' Only change the reference. 只更改参考。 That is immutable. 这是不可改变的。

final: 最后:

Actually final is a keyword.When you add it to variable, you can not change the reference. 实际上final是一个关键字。当你将它添加到变量时,你无法更改引用。

When you use keyword "final", that means that you cannot change the reference of the object that the variable points to. 当您使用关键字“final”时,这意味着您无法更改变量指向的对象的引用。 So, in this case variable "name" cannot be made to point to another string object. 因此,在这种情况下,变量“name”不能指向另一个字符串对象。 However, please note that we can change the contents of the object since we are using a final reference. 但请注意,我们可以更改对象的内容,因为我们使用的是最终引用。 Also Strings in java are inherently immutable. 此外,java中的字符串本质上是不可变的。 ie you cannot change its contents. 即你不能改变它的内容。 So, in your case, final will make a final reference to a string object. 因此,在您的情况下,final将对字符串对象进行最终引用。 and since you can't change the variable to point to another string object, code fails. 并且由于您无法将变量更改为指向另一个字符串对象,因此代码将失败。

See the code below to understand working of final variable. 请参阅下面的代码以了解最终变量的工作情况。

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 means that once the constructor for an object has completed execution that instance can't be altered. 不可变意味着一旦对象的构造函数完成执行,该实例就无法更改。

This is useful as it means you can pass references to the object around, without worrying that someone else is going to change its contents. 这很有用,因为它意味着您可以将引用传递给对象,而不必担心其他人会更改其内容。 Especially when dealing with concurrency, there are no locking issues with objects that never change 特别是在处理并发时,对于永不改变的对象没有锁定问题

eg 例如

class Foo
{
     private final String myvar;

     public Foo(final String initialValue)
     {
         this.myvar = initialValue;
     }

     public String getValue()
     {
         return this.myvar;
     }
}

Foo doesn't have to worry that the caller to getValue() might change the text in the string. Foo不必担心getValue()的调用者可能会更改字符串中的文本。

If you imagine a similar class to Foo, but with a StringBuilder rather than a String as a member, you can see that a caller to getValue() would be able to alter the StringBuilder attribute of a Foo instance. 如果你想象一个类似于Foo的类,但是使用StringBuilder而不是String作为成员,你可以看到getValue()的调用者能够改变Foo实例的StringBuilder属性。

final is a reserved keyword in Java to restrict the user and it can be applied to member variables, methods, class and local variables. final是Java中的保留关键字,用于限制用户,它可以应用于成员变量,方法,类和局部变量。 Final variables are often declared with the static keyword in Java and are treated as constants. 最终变量通常在Java中使用static关键字声明,并被视为常量。 For example: 例如:

public static final String hello = "Hello"; public static final String hello =“Hello”; When we use the final keyword with a variable declaration, the value stored inside that variable cannot be changed latter. 当我们将final关键字与变量声明一起使用时,存储在该变量中的值不能在后面更改。

For example: 例如:

public class ClassDemo {
  private final int var1 = 3;
  public ClassDemo() {
    ...
  }
}

Note: A class declared as final cannot be extended or inherited (ie, there cannot be a subclass of the super class). 注意:声明为final的类不能被扩展或继承(即,不能有超类的子类)。 It is also good to note that methods declared as final cannot be overridden by subclasses. 值得注意的是,声明为final的方法不能被子类覆盖。

Benefits of using the final keyword are addressed in this thread 在此主题中解决了使用final关键字的好处

final String name = "John";

When you write the above your code is telling the compiler that the reference name will always point to the same memory location. 当您编写上述代码时,您的代码告诉编译器引用name将始终指向相同的内存位置。 Now why I say memory location because it might happen that the object the reference is pointing to is mutable like array or list of integers. 现在为什么我说内存位置,因为它可能发生引用所指向的对象是可变的,如数组或整数列表。 So if I say final int[] arr = {5,6,1}; 所以如果我说final int[] arr = {5,6,1}; I can do arr[2] = 3; 我可以做arr[2] = 3; but I can't do arr = {3,4,5} cause you will be trying to assign a new int[] to final variable arr which is a new memory location and seeing this compiler will show error. 但我不能做arr = {3,4,5}因为你会尝试将一个新的int[]分配给最终变量arr ,这是一个新的内存位置,看到这个编译器会显示错误。

String name = "John";
name = "Sam"; 

Above the name variable of type String is immutable because String in java is immutable which means you can't change the state of the object pointed out by the reference name once it is created and even if you change it to Sam it is now a different object which is pointed by the reference name and the previous object John will have no reference and can be collected by garbage collector whenever it runs if it has no other references pointing to it. 上面的name类型的变量String不可改变的 ,因为String在java中是immutable ,这意味着你不能改变对象的状态所指出的基准name一旦创建它,即使你将它更改为Sam它现在是一个不同引用name和前一个对象指向的对象John没有引用,只要它没有指向它的其他引用,它就可以被垃圾收集器收集。

Immutable : String and wrapper classes are immutable. 不可变:字符串和包装类是不可变的。 Because of the String constant pool they can't change their value inside an object, but they can change references of object holding different values. 由于String常量池,它们无法在对象内更改其值,但是它们可以更改包含不同值的对象的引用。

String s1 = new String("cant't change");

Final : when we create a reference of String 最后:当我们创建String的引用时

Final String s2 = "cant't change";

The reference for s2 is pointing to object which has value " can't change" inside it. s2的引用指向其内部具有值“无法更改”的对象。

The reference s will now always point to the object holding value "can't change". 现在,引用s将始终指向保持值“无法更改”的对象。 It's reference can't be changed. 它的参考不能改变。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM