我认为这是一个非常愚蠢的问题,但我终其一生都无法理解 API(例如 Java Sound API)和包(例如 Sound 中的 javax.sound.sampled)这一事实。 API)包含接口,这些接口中的方法可以方便地调用。
如果接口没有方法定义,调用什么?
您不能实例化接口,只能实例化实现接口的类。
private Clip m_clip;
这不会实例化或调用任何东西。Clip
它只是声明了一个变量,您可以在其中存储对实现接口(或null
)的对象的引用。
对象可以用接口类型声明,但只能用具体类型初始化。所以
private Clip m_clip;
很好,因为它只是一个声明。在使用之前m_clip
,需要对其进行初始化,即使其指向一个有效的对象。
m_clip = new Clip();
会产生编译错误,因为作为Clip
接口,无法实例化。然而,
class MyClip implements Clip { ... }
...
m_clip = new MyClip();
可以:MyClip
是实现接口的具体(非抽象)类Clip
,因此可以在需要时实例化和使用它Clip
。在此语句之后, is 的静态类型(这是编译器在编译时知道的类型,也是客户端知道的类型),但它的动态或运行时类型是. 这不是由编译器跟踪的,也不一定是客户端知道的。m_clip
Clip
m_clip
MyClip
m_clip
. 根据这个简单的例子,这可能看起来很奇怪,但考虑到实际的对象可能是从一个方法返回的,该方法可以在另一个类中,不是你写的,所以没有人知道里面发生了什么。使用的具体类型甚至可能对外界不可见。
一旦你初始化m_clip
,它的客户就可以使用它(例如调用它的方法)。但是他们只看到它的公共接口,即在. 中声明的方法Clip
。这一切听起来可能很复杂,但它有一个了不起的优势:可以随时更改实际(运行时)类型,而不会影响其客户端。m_clip
例如,通过将上面的行更改为
m_clip = new SomeOtherClip();
它的实现发生了变化,但它的客户仍然可以使用它,而无需更改其代码中的任何内容。
您应该阅读有关 Java Sound API 及其服务提供者接口的文档。Java Sound API Guide 的第 1 章解释了 API 的设计、实现以及实现服务提供者接口的不同提供者可以扩展实现的方式。
简而言之,接口的实现存在,但应用程序开发人员无法直接访问这些类。
在 Java 6(在 Windows 中)中,默认的 Java Sound 实现由 rt.jar 中包含的 com.sun.media.sound 包和名为 jsound*.dll 的 DLL 实现。SPI 模型允许其他服务提供者替换或扩展实现。我找到了另一个 StackOverflow 答案,它解释了 SPI 模型在 Java 中的工作原理