我的目标是让Java对象不可变。我有一个班级< code >学生。为了实现不变性,我用以下方式对它进行了编码:
public final class Student {
private String name;
private String age;
public Student(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
我的问题是,实现学生
班级不变性的最佳方法是什么?
如何使可变对象不可变?
来源
我们为什么要创建不可变的对象?
不可变对象只是其状态(对象的数据)在构造后无法更改的对象。
来源
在Java中,字符串是不可变的,它提供了诸如缓存,安全性,无需复制即可轻松重用等功能。源
在创建不可变类时,您必须考虑一些事情:
对于第四点,假设您的类中有一个<code>Date<code>字段,那么该字段的getter应该如下所示:
public Date getDate() {
return new Date(this.date.getTime());
}
制作防御性副本可能会成为一个令人头疼的问题,当你的可变字段本身由一些可变字段组成时,而这些可变字段又可能包含一些其他可变字段。在这种情况下,您需要以迭代方式复制它们中的每一个。我们将可变字段的迭代副本命名为深度复制。
自己实现深度复制可能很麻烦。但是,撇开这个问题不谈,你应该再次考虑你的类设计,一旦你看到自己陷入了制作深度防御性副本的要求。
严格来说,你的类不是不可变的,它只是有效地不可变。要使其不可变,您需要使用 final
:
private final String name;
private final String age;
尽管这种差异看起来很微妙,但它在多线程上下文中会产生重大影响。不可变类本质上是线程安全的,有效的不可变类只有在安全发布时才是线程安全的。
由于这是一个热门的话题,这些天,我无法理解某些概念。请原谅,如果我听起来很愚蠢,但当我试图创建不可变对象时,我发现大多数帖子如下 null null 此测试用例失败并打印Cassandra。 如果我做错了什么让我知道。
问题内容: String abc[]={“abc”}; String def[]={}; 通过更改“ def”对象,我的abc对象也被更改。在String []数组旁边有这个特性还有什么其他的Java对象有类似的特性?能解释更多吗?为了防止在更改def时更改abc,我必须执行def = abc.clone();。 问题答案: 您将对象的可变性/不可变性与引用值的复制混淆了。 在这些图中,是参考变量
问题内容: 我正在努力使可变对象与不可变对象有关。使用可变对象会带来很多负面影响(例如,从方法中返回字符串数组),但是我很难理解它的负面影响。使用可变对象的最佳实践是什么?您是否应尽可能避免使用它们? 问题答案: 好吧,这有几个方面。 没有参考身份的可变对象会在奇数时间导致错误。例如,考虑使用基于值的方法的 : 当实例用作键时,实例在映射中“丢失”,因为实例和相等性基于可变值。这些值在映射之外更改
问题内容: Java中不变对象的优点显而易见: 一致状态 自动线程安全 简单 您可以通过使用私有final字段和构造函数注入来支持不变性。 但是,在Java中偏爱不可变对象有哪些弊端? 即 与ORM或Web演示工具不兼容? 不灵活的设计? 实施的复杂性? 是否可以设计一个主要使用不可变对象的大规模系统(深层对象图)? 问题答案: 但是,在Java中偏爱不可变对象有哪些弊端?与ORM或Web演示工具
问题内容: 代码段-1 代码段-2 我在第一个代码段中遇到了竞争。我知道这是因为我正在获得对不可变对象(类型为Integer)的锁定。 我已经写了第二个代码片段,这再次使“布尔”不变。但这有效(输出运行中不显示竞争条件)。如果我正确理解了上一个问题的解决方案,则以下是出现问题的一种可能方法 线程1锁定由指向的对象(例如A) 线程2现在试图获取由指向的对象的锁,并进入A的等待队列。 线程1进入同步块
我正在使用JAXB从XSD文件创建Java对象。我正在创建不可变包装器来隐藏由JAXB生成的对象(之前我更新了JAXB对象,以实现不可变接口并将接口返回给客户机。但意识到改变自动生成的类是不好的,因此使用包装器) 目前,我正在将这些不可变的包装返回到客户端应用程序。是否有任何选项,使自动生成的类将是不可变的,并避免创建不可变包装器的额外工作。任何其他方法都是鼓励的。 谢谢