我读到有很多理由让我们在SO线程和arcticle中进行最终的决赛。 其中两个是
1. To remove extensibility
2. to make class immutable.
使一个类不可变具有与它一样的特性作为final(它的方法)吗?我没有看到两者之间的区别?
答案 0 :(得分:2)
Immutable object不允许改变他的状态。最终类不允许继承自己。例如,类Foo
(见下文)是不可变的(状态,即_name
永远不会更改),类Bar是可变的(rename
方法允许更改状态):
final class Foo
{
private String _name;
public Foo(string name)
{
_name = name;
}
public String getName()
{
return _name;
}
}
final class Bar
{
private String _name;
public Bar(string name)
{
_name = name;
}
public String getName()
{
return _name;
}
public void rename(string newName)
{
_name = newName;
}
}
答案 1 :(得分:0)
将类型识别为“可验证的深度不可变”有时会很有用,这意味着静态分析可以证明(1)一旦构造了一个实例,它的所有属性都不会改变,并且(2)每个对象实例都是它具有参考价值,可以证实是不可改变的。对扩展开放的类不可能是可验证的深度不可变的,因为静态分析器无法知道是否可以创建可变子类,以及对可变源子类的引用存储在应该是可验证的深度不可变对象中。 / p>
另一方面,有时候抽象(因此可扩展)的类被指定为深度不可变的有时是有用的。抽象类无法将派生类强制为不可变类,但任何可变派生类都应该被视为“已损坏”。这种情况有点类似于两个报告自己彼此“相等”的对象实例应该报告相同的哈希码的要求。设计违反该要求的类是可能的,但是导致的任何错误的哈希表行为都是破坏的哈希代码函数的错误,而不是哈希表。
例如,可能有一个抽象的ImmutableMatrix属性,其中包含一个读取给定(行,列)位置元素的方法。一种可能的实现方式是使用N * M个元素的阵列来支持NxM ImmutableMatrix。另一方面,定义一些子类(如ImmutableDiagonalMatrix)和N个元素的数组也是有用的,其中Value(R,C)
将为R!= C产生0,而Arr[R]
用于R == C 。如果使用的阵列的很大一部分是对角线阵列,则可以为每个这样的实例节省大量内存。虽然让类可扩展可能会让人有可能以一种可以突变的方式扩展它,但它也会让程序员知道程序所使用的许多数组符合某种特定形式的可能性设计一个类来优化存储该形式。