[英]About the Java interface and polymorphism
我在阅读Java doc时遇到了一个奇怪的案例。 以下是Arrays.asList方法中Oracle java文档的链接, http: //docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#asList (T ...)
文档中有一个例子
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
我的问题是,由于List是一个接口,为什么我们可以将stooges声明为'List',而不是实现List的具体子类(例如ArrayList或LinkedList)? 那么这是否意味着我们可以有一个接口类型的引用变量? 它看起来很奇怪,因为我一直认为接口只代表多态,我们永远不应该真正使用接口类型变量。
有谁能请给我一些线索?
将List接口视为保证。 任何实现List的类都将保证具有接口的方法。 当Arrays.asList()返回一个List,你实际上并没有获得一个接口时, 你会得到一个具体的类,保证实现List接口中列出的方法 。
至于你的“我们永远不应该真正使用接口类型变量”,你实际上是想这样做。 它被称为“编程到界面”。 如果你可以返回List而不是像LinkedList这样的东西,它会更加灵活。 您的方法的调用者没有耦合到您可能使用和返回LinkedList的特定实现内部实现。 如果在某些时候您想要返回ArrayList而不是LinkedList,则调用者不必更改任何代码,因为他们只关心接口。
简而言之,Serializable是一个标记界面,因此有点奇怪。 它并不保证方法存在,而是保证实现serializable的类的创建者已经考虑了与序列化类相关的许多问题(重写readObject / writeObject,与其他序列化表单的兼容性以及其他问题http: //www.javapractices.com/topic/TopicAction.do?Id=45 )。 所以Serializable仍然提供像List一样的保证,但它不是关于方法签名,而是关于语言的语言特征。
使用接口作为引用类型是Java中完全有效的实践。 例如, Serializable
接口将在它的类中执行此操作,以便可以序列化传递给它的任何对象。
这也是Java提供类似于多重继承的东西的方式。 例如:
public interface A { }
public class B implements A {}
public class program {
B bClass = new B();
A aObject = (A)bClass;
}
这样,可以使用不同的引用类型引用相同的对象,并且不会弄乱继承链!
接口定义了实现的contract
或specification
。 哪种方法及其签名。 因此,实现接口的类必须尊重该contract
。 这样,您可以更改实现,而不会影响使用接口声明变量的代码。
在你提到的例子中:
除非您查看代码,否则您不知道Arrays.asList
正在使用List
接口的实现。 那么你怎么知道使用哪一个? (有关列表界面,请参阅javadoc以了解它具有哪些实现)
实现可能会发生变化,如果Arrays.asList
决定使用其他实现呢? 你的代码将被破坏。
方法Arrays.asList
的签名是它返回List<T>
所以如果你想要一个具体的实现作为变量你必须Arrays.asList
那个不好的做法的返回值或创建新的 - 让我们说ArrayList
- 和将所有元素复制到其中,这只是一个不必要的开销。
Bloch的Effective Java是一本关于Java最佳实践的好书。 特别是, 第52项讨论了这个问题:“如果存在适当的接口类型......使用接口类型声明。”
一般的概念是,为了获得最大的灵活性和可理解性,您应该使用最能反映上下文的类型,通常是接口。 在这个例子中,您提供了确切的实现,或者只是它是一个List。 当然,如果代码需要特定于ArrayList的方法,或者代码依赖于特定于ArrayList的行为,那么请使用具体类。
偶尔有例外,例如使用GWT-RPC时 ,这是出于实现原因。
这是多态性能力的一个很好的例子,如果你喜欢你可以查看Arrays.asList()这里的Arrays.asList(T ... a)的源代码,你会发现它需要varibale长度输入并定义它自己的私有静态具体类ArrayList实现List接口而不是使用众所周知的java.util.ArrayList或其他java Collection类型,这可能是为了使它更高效或者某种东西,你想要实现自己的类并将它返回到用户没有通过实现细节压倒他,因为有一个接口他可以处理你的私人课程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.