说我有一个不可变的DecimalNumber
类:
public final class DecimalNumber {
public final String str;
public DecimalNumber(String str) { this.str = str; }
public DecimalNumber(DecimalNumber copy) { this(copy.str); }
public boolean isZero() {...}
public DecimalNumber add(DecimalNumber other) {...}
...
}
我决定像这样实施add
:
public DecimalNumber add(DecimalNumber other) {
if (other.isZero())
return /* the same object */
...
}
我应该返回this
(内存使用量减少)还是复制对象new DecimalNumber(this)
?
我认为简单地返回this
应该没问题,但是创建新对象是有益还是有理由?或者它是首选的?
答案 0 :(得分:2)
如果一个类是不可变的并且是final,那么你可以返回this
。
如果它不是最终的,则无法确定this
实例是否真的不可变。您实际上可能正在处理一个增加可变状态的子类。
请注意,在以下情况下,类只是真正不可变的:
在您的情况下,这两个条件得到满足,因为String
是一个不可变类。如果你知道你的类没有子类存在,那么你可以(事实上,应该恕我直言)返回this
。为了确保您的类的子类不存在,您可以将其设为final
。
答案 1 :(得分:1)
为什么回归this
感到奇怪?
如果你要返回一个新对象,那么首先不需要if
,所以返回new DecimalNumber(this)
是没有选择的!
答案 2 :(得分:1)
由于您的对象是不可变的,我们需要在更改时创建另一个副本。但是在这里,添加零不会改变对象的值。 因此,我们可以返回相同的对象。
考虑String.java中的concat()
代码以供参考:
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
char buf[] = new char[count + otherLen];
getChars(0, count, buf, 0);
str.getChars(0, otherLen, buf, count);
return new String(0, count + otherLen, buf);
}
如您所见,返回同一个对象没有任何害处。
答案 3 :(得分:1)
无需复制不可变值对象。由于它是不可变的,因此原件和副本在所有时间都是等效的,因此有两个副本是没有意义的。
我的示例不仅仅是dataRequest = DataClass()
,我还会更进一步,完全删除你的复制构造函数。
例如,Java return this
类实际上有一个复制构造函数。但所有这一切都是由缺乏经验的开发人员编写的代码,他们要么没有意识到它是不可改变的(或者不理解这意味着什么),所以他们会String
或{{0}} {1}},它只会浪费内存和处理器周期。
答案 4 :(得分:0)
如果一个对象真的是不可变的,我会返回它。你根本不需要两个肯定总是相等的实例。
https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html