在Immutable类中创建一个字段`Final`?

时间:2014-03-14 10:21:41

标签: java immutability

最近我参加了一次采访。

我被问到如何上课Immutable

我告诉了他答案。

然后他问我为什么这些字段是final

我回答说,用户不会意外更改字段的值,如果他这样做,就会出现编译错误。

现在他问我有一个只有getter方法的immutable类。

然后在这个课程中final的用途是什么?

我无法回答。他说这背后有一个原因。

有人可以解释一下吗?

4 个答案:

答案 0 :(得分:6)

来自Effective Java:

将所有字段设为最终字段。这清楚地以系统强制执行的方式表达您的意图。此外,如果对新创建的实例的引用在没有同步的情况下从一个线程传递到另一个线程,则必须确保正确的行为,如内存模型中所述。

答案 1 :(得分:2)

  

现在他问我有一个只有getter方法的不可变类。

     

然后在这个班级中有什么用途?

只有getter方法不能确保类是不可变的。如果您公开内部状态而不是客户端可以更改类的状态。

不可变意味着一旦创建对象状态就无法更改。

将所有字段设为最终并仅提供getter不会使其永远不可变。想象一下以下代码:

public class MyString {
    private final char[] content;

    public MyString(String str){
         this.content = str.toCharArray();
    }

    public char[] getContent(){
        return this.content; // internal state exposed. You should return a copy.
    }
}

这个类只有最终字段,只有getter方法,但仍然是可变的。想象一下这个客户端代码:

MyString myString = new MyString("test");
myString.getContent()[0] = 'f';
  

现在他问我有一个只有getter方法的不可变类。

     

然后在这个班级中有什么用途?

final的使用是用java的语言特性表达你的意图,因此由编译器强制执行。

因此,创建变量final对于原始类型是有益的,但是如果变量是引用,则必须小心。在这种情况下,您必须确保

  • 您引用的对象也是不可变的或
  • 只有您的实例才能访问该对象。

后者只能由程序员确保。因此,当您返回参考文献时要格外小心。

答案 2 :(得分:0)

当然,不变性当然是以使用对象的方式实现的,而不是通过强制执行。您可以随时使用Reflection更改最终字段的值。

它的使用是允许编译器阻止你破坏不变性,以及表示需要不变性(例如当你使用一个使用方法本地的内部类时)参考)。

答案 3 :(得分:-1)

'final'作为关键字的名称建议意味着最终关键字所附加的属性不能更改(就值而言),换句话说,它的行为就像一个常量。如果字段不是'final',那么就在里面本地方法,你可以改变字段的值。