首页 > 解决方案 > 为什么我要在没有设置器的情况下创建不可变类时将字段声明为最终字段

问题描述

我目前在这里阅读,为了实现我的对象的不变性,我必须:

  1. 将我的所有字段声明为私有和最终字段
  2. 不定义二传手

如果无论如何都没有设置器,为什么我需要将字段声明为 final。java编译器不允许这样的事情:

myObj.getSomething() = new Somthing()

如果我尝试使用反射,那么final关键字不会阻止我更改引用。

我在这里找到了一个很好的解释,为什么整个类都需要,final但没有关于为什么私有字段需要是最终的。

编辑:作为对 GotoFinal评论的回复, 这是一个展示如何使用反射编辑字段的类:

public class Test {
static class Immutable {
    private final StringBuilder immutableField = new StringBuilder("You can't set final field just by normal reflections");

    public StringBuilder getStringBuilder() {
        return immutableField;
    }
}

public static void main(String[] args) throws Exception {
    Immutable immutableObject = new Immutable();
    Field f1 = immutableObject.getClass().getDeclaredField("immutableField");
    f1.setAccessible(true);
    f1.set(immutableObject, new StringBuilder("Well, I just did"));
    System.out.println(immutableObject.getStringBuilder());
}

}

标签: java

解决方案


它不需要是最终的,但它是一个很好的做法,因为在阅读源代码时,您会立即知道给定字段不能更改 - 包括类内部或本地类 - 在您的类中声明(java将生成特殊的桥接器然后为那个领域)。
此外,由于字段是最终的,您需要在构造函数中对其进行初始化 - 所以在这里更难出错。

它也可能会影响反序列化器的工作方式,因为大多数库不会尝试修改最终字段。


推荐阅读