为什么Java中的许多Collection类扩展了抽象类并实现了接口?

JRo*_*mio 42 java collections

为什么Java中的许多Collection类扩展了Abstract类并实现了接口(也是由给定的抽象类实现的)?

例如,类HashSet扩展AbstractSet并实现Set,但AbstractSet已经实现Set.

Col*_*ert 32

这是一种记住这个类真正实现该接口的方法.
它不会产生任何不良影响,它可以帮助理解代码,而无需通过给定类的完整层次结构.

  • +1此外,AbstractSet的维护者可能决定更改层次结构并为将来的版本删除Set(显然不会发生,但可能会发生在其他非核心类中).在这种情况下,HashSet的编译将失败,而不是所有使用HashSet作为Set的类. (14认同)
  • 那么为什么不放一个Collection接口呢?它的愚蠢和不必要. (3认同)

Joa*_*uer 11

从类型系统的角度来看,如果类没有再次实现接口,则类将不会有任何不同,因为抽象基类已经实现了它们.

那是真的.

他们确实实现它的原因(可能)主要是文档:a HashSetis-a Set.这是通过添加明确的implements Set到最后,,虽然它不是绝对必要的.

请注意,使用反射实际上可以观察到差异,但是如果HashSet没有Set直接实现,我会很难产生一些会破坏的代码.

  • +1,例如使用`getInterfaces()`:http://ideone.com/BDpdr但是使用这种方法认为它将提供所有已实现的接口将是危险的. (3认同)

Boa*_*ann 10

这在实践中可能无关紧要,但我想澄清一下,显式实现接口与通过继承实现接口并不完全相同.不同之处在于已编译的类文件,并且通过反射可见.例如,

for (Class<?> c : ArrayList.class.getInterfaces())
    System.out.println(c);
Run Code Online (Sandbox Code Playgroud)

输出显示的是显式实现的接口ArrayList,按照它们在源代码中编写的顺序,[在我的Java版本中]是:

interface java.util.List
interface java.util.RandomAccess
interface java.lang.Cloneable
interface java.io.Serializable
Run Code Online (Sandbox Code Playgroud)

输出不包括由超类实现的接口,也不包括作为包含的接口的超接口的接口.特别是,Iterable并且Collection从上面遗漏,即使ArrayList隐式实现它们.要找到它们,您必须递归迭代类层次结构.

如果某些代码使用反射并依赖于明确实现的接口,那将是不幸的,但这是可能的,因此集合库的维护者可能不愿意现在改变它,即使他们想要.(有一种观察称为Hyrum定律:"如果有足够数量的API用户,那么您在合同中承诺的并不重要;您系统的所有可观察行为都将取决于某人".)

幸运的是,这种差异不会影响类型系统.表达new ArrayList<>() instanceof IterableIterable.class.isAssignableFrom(ArrayList.class)仍计算为true.


Nik*_*bak 6

科林赫伯特不同,我不会买那些关心可读性的人.(每个认为标准Java库都是由无可挑剔的神创造的人,应该把它看作是它们的来源.我第一次这样做时,我对代码格式化和许多复制粘贴块感到震惊.)

我的赌注是迟到了,他们累了,也不在乎.