【发布时间】:2013-07-30 09:03:36
【问题描述】:
ImmutableList的documentation says:
虽然这个类不是最终类,但它不能被子类化,因为它没有公共或受保护的构造函数。
我知道这有点牵强,但是可以在com.google.common.collect 包中创建ImmutableList 的子类(因为它的构造函数不是私有的,而是包私有的),它是可变的。从那时起,没有人得到对ImmutableList 的引用可以确定它确实是不可变的。这不破坏ImmutableList的目的吗?
【问题讨论】:
-
如果没有可见的子类如何调用父类构造函数?
-
即使构造函数是私有的,也可以使用反射改变列表。不变性不是一种安全机制。这是一种 OO 设计方式,可以避免在脚上开枪。当然,通过使用反射或定义不应该包含在您不拥有的包中的某些东西的子类来打破所有规则,是一种肯定的方式来打自己的脚。只是不要这样做。
-
@JBNizet:很好,但是 SecurityManagers 可以阻止通过反射访问字段。另一方面,包裹也可以密封保护,但不是密封的。
-
我提到的问题可以通过将类设为final或密封包来防止,所以,我不明白为什么不这样做?
-
两件事:首先这非常接近code.google.com/p/guava-libraries/issues/detail?id=1485。那么关于“final”,看一下 ImmutableList。它是抽象的。这意味着它打算被子类化。只是不被任何人。这允许基于列表包含的元素数量进行一些优化。例如,存在大小为零的情况:对于这种情况,总是返回相同的列表。另一种情况是大小为 1:单例列表可用(但显然效率低下)。其余的是更常规的 ImmutableList 实现。