定义不可变类的策略表明
所有字段都应该是最终字段。
对于ex:
private String name;
为什么一定要最终决定?
因为我没有给出setter方法吗?它不能改变。谢谢。
最终值
强调了它不能在其他任何地方更改的事实。因此,final
在许多方面有助于使对象不可变。
主要原因(IMHO)是,当字段是final时,保证在构造函数完成后立即在其他线程中可见。
如果你读
private final String name;
你知道这个字段是不变的。
如果你读
private String name;
你必须阅读整个课程,以检查它在任何地方都没有改变。这意味着你要做更多的工作。
现在你可能还记得,刚写完这个类,你没有添加setter,但是在写了更多的类之后,你在六个月后阅读了自己的类,你就记不住了。
即使现在没有更改,也有人(可能是你自己)可以稍后通过添加代码来更改它。但是,您可能已经假设该值不会改变。
简而言之,只有当您的意思是要改变的值时,才使它成为非最终值,当您不期望它改变时,才使它成为最终值。不要把它留作可能是/可能不是。
现在想象一下,你已经习惯于清楚哪些字段可以更改,哪些字段不能更改。在阅读其他人的代码时,这可以节省大量工作。但是你发现你正在阅读的代码不清楚,不确定,这并不意味着它被修改了,现在意味着你必须检查一些东西,你通常不需要检查,这是在试图理解一些你真的不需要的代码时又一个头疼的问题。
一个简单的例子,说明阅读代码来确定一个字段是否是有效的最终字段有多难。
public class A {
static class B {
private int x;
}
// some code
到目前为止,这一切看起来都很好,B
中没有设置程序,甚至没有方法。所以B.x
是不变的,对吗?
static class C {
public void update(B b, int x) {
b.x = x; // this really compiles
}
}
}
哦,不,你必须阅读整个类文件。
当你编写代码时,最好让你能的每一个字段都是最终的
(这应该是默认的IMHO),而不是让别人稍后去弄清楚。
如果我有一个可序列化的类, } 当我使用以下消息构建findBugs时,会显示此消息: 这个可序列化类定义了一个非原语实例字段,它既不是瞬态的、可序列化的,也不是java的。并且似乎没有实现可外部化的接口或readObject()和writeObject()方法。如果此字段中存储了不可序列化的对象,则此类的对象将无法正确反序列化。 田野应该是什么才不会看起来像虫子?
问题内容: 我正在阅读Joshua Bloch撰写的Effective Java 项目15 。在第15项中,谈到“最小化可变性”时,他提到了使对象不可变的五个规则。其中之一是使所有字段最终确定。这是规则: 将所有字段都设为最终字段 :这可以通过系统强制地表达您的意图。同样,如果对新创建实例的引用从一个线程传递到另一个线程而没有同步,则必须确保正确的行为,如在内存模型中阐明的那样[JLS,17.5;
问题内容: 我正在浏览规范,并发现不可能在内部类中拥有不是最终编译时间常数的静态成员。 而为什么呢?为什么我们可以在内部类中拥有静态的final成员,却不能拥有static方法?它可以从其所有者类继承静态成员。但是为什么不应该呢?OOP的主要原理是什么? 问题答案: 您的课程未声明为静态。那么,它具有静态场到底意味着什么呢? 可不可能是 对于所有实例,无论封闭实例如何都一样? 对于具有相同封闭实例
有一个问题,为什么他们要求在字典中使用不可变对象作为键。 当我最近使用字典(显然不是为了哈希表)将Xml节点对象作为键放置时,这个问题实际上进入了我的脑海。然后,我在使用过程中多次更新节点。 那么,“使用不可变键”到底意味着什么呢?
问题内容: 在中,所有需要锁定的方法都将final在调用之前将其复制到局部变量。 没有任何理由复制到一个局部变量时,现场的? 此外,在执行操作之前,它还会使用的本地副本: 有什么理由将最终字段复制到本地最终变量? 问题答案: 该类的作者Doug Lea喜欢使用这种极端的优化方法。这是有关core-libs-dev邮件列表的最新主题的帖子,有关这个确切的主题,可以很好地回答您的问题。 从帖子中: …
问题内容: 我在网上找不到任何参考资料。但是只是想知道类中的最终字段应该一直还是只是一个约定。基于对它们的用法的理解,我觉得这比语言所强加的东西更合乎逻辑。 问题答案: 当然不是。如果它们属于该类,则必须是静态的;如果它们属于该类的实例,则必须是静态的: