可能重复:
编码到接口?
我正在阅读 Java 中的 Collections 教程,它强烈建议使用其接口类型而不是其实际实现类型来实现引用 Collections 的代码。例如:
Set<String> s = new HashSet<String>();
它说如果我以后决定更改它,它将给我更改实现的灵活性。
Set<String> s = new TreeSet<String>();
除了灵活性之外,使用其接口类型实现集合还有其他好处吗?
可能重复:
编码到接口?
我正在阅读 Java 中的 Collections 教程,它强烈建议使用其接口类型而不是其实际实现类型来实现引用 Collections 的代码。例如:
Set<String> s = new HashSet<String>();
它说如果我以后决定更改它,它将给我更改实现的灵活性。
Set<String> s = new TreeSet<String>();
除了灵活性之外,使用其接口类型实现集合还有其他好处吗?
是的,当使用接口类时,您将只能访问最默认的方法。这些方法保证是直观的。在使用实现类时,您可能会看到更多可能使您感到困惑或被滥用的方法。
例如:一个集合接口将有一个返回元素数量的方法,比如说:size()
. 但是实现类也可能提供一个capacity()
方法来告诉你底层数组有多大。
但正如教程告诉你的那样,最重要的原因是你可以毫不费力地更改实现。在非常特殊的情况下,更改实现可能对性能优化很有趣。
我认为这里不仅仅是集合,它与多态性有关:最好将接口用作声明的类型,因为您可以更改实现和/或具体类以在运行时绑定。(这里的讨论可能会更长 - 有很多关于此的文档/教程 - Java 基础知识)
接口类型通常包含比实际实现更少的方法,因此很容易使用后者,因为它允许访问它们。
但是,这会以一种重要的方式束缚您的双手。例如,如果您决定Vector
从使用向量的类的公共方法中公开返回类型 ,但后来意识到您的模块可以更好地使用 a LinkedList
,那么您现在遇到了一些问题——这将破坏任何使用返回向量的方法。
另一方面,如果你一开始就使用了返回类型,List
那么就不会有问题——你可以将内部 Vector 切换为 LinkedList,或者实现你自己的实现接口 List 的东西。以我的经验,这是一个常见的事件(当然,如果你让它变得困难或不可能,那么它就会发生更少)。
因此,除非您有特定的理由不这样做(例如,您需要提供对仅可用于向量的方法的访问),否则请始终使用通用接口类型作为返回值。
我意识到这仍然与灵活性有关,但是从您的帖子中不清楚您是否了解灵活性的重要性。如果您要求使用接口的更好理由,即。“如果我不在乎灵活性,是否可以使用特定的实现”,即。“我不关心灵活性,想要使用特定类型,可以吗?” 答案是您应该关心灵活性;) 正如其他人所说,这是良好的 Java 编程的重要基础。