类集合有一些静态方法作为实用工具来操作集合,如List。例如,排序方法(Collections.sort(list))。我不理解为什么Java规范制作了另一个类来承载排序方法(以及所有其他类,如binarySearch),而不列出接口和具体的子类,如ArrayList和LinkedList,来实现这些方法。
已更新
当我做了一个全球性的研究并阅读了这篇文章的答案时,我不得不说(鸟瞰图):一些人(我提到@dan,@WJS,@cdalxndr)在这篇文章中说,以排序方法为例,因为ArrayList和LinkedList的排序可以用相同的方法完成,所以我们只能实现一次编写。所以(我说)我们可以将代码放在列表接口中,但在Java 7之前,我们无法将任何实现放在接口的主体中,编写一次的唯一方法是在实用类中实现。但由于Java 8接口具有“默认”方法的特性。Java团队利用这一特性在接口级别实现了排序方法,ArrayList和LinkedList可以使用该方法(如果类不覆盖它,则默认使用该方法)
从Java8开始有一个选项,只需要您定义(或使用预定义的比较器)。
下面的虚拟示例:
List<Integer> list = new ArrayList();
list.addAll(List.of(1,5,4,3,6,8,9,2));
list.sort(Comparator.naturalOrder());
但很明显,对于作为用户的您来说,它并不像Collections util中那样做(尽管我确实相信Collections实现也会使用类似的比较器)。
排序是一种算法,而列表是一个容器。
开发人员希望将列表算法(排序、二进制搜索等)与容器逻辑(添加、删除等)分离,因此他们将算法放在实用类集合中。
Java之前
因此,除非您想强制所有实现从提供这些方法的抽象基类继承,否则您必须小心添加到接口的内容。
即使使用默认方法,您也必须小心,以避免用太多方法污染实现类的名称空间。这也可能是为什么没有将Java中的每个操作都改装为默认方法的原因
虽然向接口添加default
方法的侵入性较小,因为它不会产生在已经存在的实现类中实现它的需要,但它仍然可能导致与实现类的具体方法发生冲突没有在以前的版本中实现接口方法。
想象一下预Java中的自定义List
实现
尽管如此,排序
方法已被添加到List
接口中,因为它具有直接的好处。与Collments
实用程序类中的静态
方法不同,默认
方法可以被覆盖。这已针对最常用的列表类型、ArrayList
、Vector
以及Array.asList(...)
返回的实现完成。由于所有这些实现都由数组支持,因此覆盖方法可以直接使用支持数组委托给Arrays.sort
,而默认
实现将使用列表内容的临时副本。
还值得注意的是,Collection
中的那些方法似乎最初是基于这些算法适用于所有类型的实现的假设,这并不成立。引入Collection API后的两个版本,引入了RAnywhere Access
标记接口,以区分两个根本不同的列表实现类别,因此静态方法可以在此基础上分支到两个替代算法。
每当我们必须基于我们正在操作的类进行分支时,我们可以质疑抽象并说我们可能最好在类型本身上使用可覆盖的方法,但如上所述,设计有历史原因,并且仍然有理由在向接口添加方法时要小心。
我正在对实现接口的类的对象进行流式处理。我希望将它们收集为接口的元素列表,而不是实现类。 对于Java16.0.1的方法,这似乎是不可能的。例如,在下面的代码中,最后一条语句将无法编译。 我们可以显式地将每个元素从转换为。但至少为了简洁起见,我们可以使用。 为什么我不能在Java 16中使用Stream#ToList来收集类的接口列表? 如果有人有比明确选角更好的解决方案,我也很乐意听到:)
问题内容: 以下接口和类已成功编译。 问题在下面的输出中提到: 输出: X 瞧,MyInterface是一个接口, 那为什么编译器允许编译 mi.getClass(),mi.wait()。 或如何在接口中使用Object类的方法。 ÿ 编辑 :-我接受拒绝的答案,因为这是最具解释性的。但是在阅读了答案之后,又出现了一个问题:- “ 请记住,如果接口试图在Object类中声明一个声明为’final’
问题内容: 我正在阅读有关如何正确执行数组深拷贝的信息,但是我对如何实现数组感到困惑。它是该类的成员,但是,如果您阅读javadocs: 首先,如果此对象的类未实现Cloneable接口,则将引发CloneNotSupportedException。 那么为什么要首先定义方法呢?当然,如果仅当存在接口时才可以使用方法,则可以将方法放在接口中。该接口本身是空的; 它只是Java用来确保使用该方法合法
我正在阅读如何正确执行数组的深度复制,但是我对是如何实现的感到困惑。它是类的成员,但是如果您阅读Javadocs: 首先,如果该对象的类没有实现接口Cloneable,则抛出CloneNotSupportedException。 为什么Java要这样做?我肯定他们有正当的理由,但我似乎想不通。
问题内容: 该主题充分说明了这一点-为什么不能在接口中声明静态方法的原因是什么? 上面的代码给了我以下错误(至少在Eclipse中):“接口方法ITest.test()的非法修饰符;仅允许public&abstract”。 问题答案: 这里有一些问题。第一个问题是声明静态方法而不定义它的问题。这是之间的区别 和 由于Espo提到的原因,第一个是不可能的:你不知道哪个实现类是正确的定义。 Java
问题内容: 编辑: 从Java 8开始,接口中现在允许使用静态方法。 例子如下: 当然这行不通。但是为什么不呢? 可能的问题之一是,当你致电时会发生什么: 在这种情况下,我认为它应该只调用一个空方法(即{})。所有子类都将被强制实现static方法,因此在调用static方法时它们都很好。那为什么不可能呢? 编辑:我想我正在寻找比“因为这就是Java的方式”更深的答案。 有特定的技术原因为什么不能