我刚刚注意到 java.util.Observable 是一个具体的类。由于 Observable 的目的是扩展,这对我来说似乎很奇怪。以这种方式实施是否有原因?
我发现这篇文章说
observable 是一个具体的类,因此必须预先确定从它派生的类,因为 Java 只允许单继承。
但这并不能真正向我解释。事实上,如果 Observable 是抽象的,用户将被迫确定派生自它的类。
我刚刚注意到 java.util.Observable 是一个具体的类。由于 Observable 的目的是扩展,这对我来说似乎很奇怪。以这种方式实施是否有原因?
我发现这篇文章说
observable 是一个具体的类,因此必须预先确定从它派生的类,因为 Java 只允许单继承。
但这并不能真正向我解释。事实上,如果 Observable 是抽象的,用户将被迫确定派生自它的类。
很简单,Observable是一个类,无论是抽象的还是其他的,这是一个错误。
Observable
应该是一个接口,JDK应该提供一个方便的实现(很像List
一个接口和ArrayList
一个实现)
java中有不少“错误”,包括:
Arrays.toString(array)
作默认值toString()
(这导致了多少 SO 问题?)Cloneable
不应该是标记界面;它应该有clone()
方法并且不Object.clone()
应该存在在soapbox上,就语言本身而言,恕我直言:
==
应该执行该.equals()
方法(这会导致很多头痛)==
应该===
像 javascript 或类似的专用方法boolean isIdentical(Object o)
,因为您几乎不需要它!<
应该compareTo(Object o) < 0
为Comparable
对象执行(类似地为>
, <=
, >=
)作为第一种方法,人们可能会认为这样做是为了允许用户使用组合而不是继承,如果您的类已经从另一个类继承,并且您也不能从 Observable 类继承,这将非常方便。
但是如果我们查看 Observable 的源代码,我们会看到有一个内部标志
private boolean changed = false;
每次调用 notifyObservers 时都会检查:
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed) return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
但是对于由这个 Observable 组成的类,我们不能更改这个标志,因为它是私有的,并且提供的用于更改它的方法是受保护的。
这意味着用户被迫继承 Observable 类,我想说缺少“abstract”关键字只是一个“错误”。
我会说这门课完全是一团糟。