Java错误:发现接口...但是期望的是类

47

我从我的代码中得到了一个奇怪的运行时错误:

"Found interface [SomeInterface] but class was expected"

这是怎么发生的?接口怎么会被实例化?

更新:(回应一些答案)我正在编译并运行相同的库,但我正在使用Guice为这个特定的接口注入提供程序。

当我将一个实现绑定到接口时,问题就解决了(似乎@ImplementedBy注释不够用)。

我更感兴趣的是Guice实际上如何管理实例化接口的机制。

5个回答

80

当运行时类路径与编译时类路径不同时,就会出现这种情况。

当应用程序被编译时,一个名为SomeInterface的类存在。

当应用程序在运行时,在编译时存在的SomeInterface将存在为一个接口(而不是一个类)。

这会导致一个IncompatibleClassChangeError在运行时抛出。

如果在编译时类路径和运行时类路径上拥有不同版本的jar文件,这是一种常见情况。


堆栈跟踪纯粹在我的代码中(因此对其他人没有用)。这就是我觉得奇怪的地方。它几乎看起来像Guice成功创建了一个接口实例。 - levik
我有同样的问题。当我尝试安装joodo(一个Clojure框架)时发生了这种情况,现在lein命令无法工作。我该如何解决这个问题? - rzv
当使用Mockito模拟接口时,可能会出现同样的奇怪问题。我今天发现了这个问题... - Dave
不错。当我将一个接口更改为抽象类时,在Maven项目中遇到了这个问题。所以首先执行 mvn clean - skytreader
1
在多模块项目中也可能会发生这种情况。对整个项目进行完全重建可以帮助解决它。 - Sunil Kumar
一个可能的情况是,当您更新依赖列表中的一个jar时,但您没有更新它的依赖项。因此,如果主要的新jar是使用其依赖jar的更新版本编译的,则可能会出现此错误。 - Victor

8

很可能代码是编译在一个库中的类上,而你运行的版本将其更改为接口。


一个简单的一次性完整重建项目就可以完成任务。谢谢! - Hartmut Pfarr

2

我有同样的问题。我的应用程序使用了两个jar库。其中一个库是建立在另一个库之上的。

库A定义了顶层类和接口。库B需要使用库A。

这是库B中使用的一些代码的伪代码:

TheInterface instance = new TheClass();
instance.someMethod();

显然,库A比库B更新,而TheInterface不再包含someMethod,但TheClass仍然包含。唯一的解决方法是获取其中一个jar的源代码,并手动更改这些内容(如果可能的话)。

2
这件事发生在我运行 maven build 时。
根据我的了解(以及 Jared 的 回答),原因是我的有效 pom.xml 中指定了同一个第三方 jar 包的两个版本。一个版本作为 传递依赖项 被引入,另一个版本由我在本地的 pom.xml 中指定。
因此,在编译时,它引用旧版本,在运行时引用新版本。
我删除了在本地 pom.xml 中指定的版本,问题得以解决。
当然,第三方库在不同版本之间可能会破坏向后兼容性,并将类更改为接口或反之。但他们有权这样做。

1

听起来你做了

class MyClass extends SomeInterface

实际上应该是这样

class MyClass implements SomeInterface

我是对的吗?

编辑:哦,你说这是一个运行时错误而不是编译时错误?让我找找看...

编辑2:看起来Jared有正确的答案。无论如何,尝试扩展一个接口实际上会在编译时给出一个"此处不应该有接口"的消息,而不是一个"找到接口但期望的是类"的错误。


也许代码是针对一个类编译的,但是现在存在的 .class 文件是另一个版本,已经变成了一个接口。 - chburd
@chburd:是的,看起来我接近了但不太对。 :) - Michael Myers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接