我对不变模式有一些疑问。首先要解决该问题,我们需要确保以下几点:
1)访问属性的实例方法不得更改实例变量。
2)确保不可变类的构造函数是唯一 实例变量的值已设置或修改。 我认为通过将incident变量作为最终变量,那么如果存在更改此变量的方法将失败,即使构造函数也将无法更改此变量,因此,如果我们需要考虑这两个语句,为什么呢?可以使用最终关键字??我知道我想念一些东西。
答案 0 :(得分:2)
制作真正的不可变品有一件重要的事情。组件可能是可变的数据结构,例如java.util.Date
。以这个简单的类为演示目的:
final class DateWrapper {
private final Date date;
public DateWrapper(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}
现在您可以编写以下代码:
DateWrapper dw = new DateWrapper(new Date());
dw.getDate().setYear(2020);
这将修改类date
的对象dw
的实例变量DateWrapper
。因此,此类并非真正不变。
要解决此问题,您必须制作如下防御副本:
final class DateWrapper {
private final Date date;
public DateWrapper(Date date) {
// It must not be possible to modify the date after construction.
// So use a copy of the original object in class DateWrapper.
this.date = new Date(date.getTime());
}
public Date getDate() {
// It must not be possible to modify the date in DateWarapper
// So return a copy.
return new Date(date.getTime());
}
}
因此,其他任何类都无法获得对DateWrapper
内部的可变引用。
另一个规则是:使您的类成为最终类,否则子类可以充当不可变的类,从而打破了不可变性的约定。这是一个恶意子类的示例,仅当DateWrapper不是final时,该子类才有效:
class Date2Wrapper extends DateWrapper {
final Date date2;
public Date2Wrapper(Date date) {
super(date);
this.date2 = date;
}
public Date getDate() {
return date2;
}
}
答案 1 :(得分:1)
首先,所有设计模式均不限于Java。它们可以用不同的语言实现,具有不同的风格。并非所有语言都具有final,即使java从一开始就没有final。
但是考虑到java的严格情况,final不能确保不变性:
例如:
Ball ball = new Ball();
ball = ball.makeRed();
在这种情况下,球是另一个球对象(使球克隆球并更改颜色)。当我们在String对象上运行方法时,也会发生同样的情况,将创建一个新的String对象以反映更改并返回:
String ball = 'Blue Ball';
ball = ball.replace('Blue', 'Red');