我的代码中出现了一个奇怪的运行时错误:
"Found interface [SomeInterface] but class was expected"
这怎么可能发生?如何实例化接口?
更新(回答一些答案)我正在针对同一组库进行编译和运行,但我我使用Guice注入此特定接口的提供者。
当我将一个实现绑定到接口时,问题就消失了(似乎@ImplementedBy注释还不够)。
我对Guice设法实际实例化接口的机制更感兴趣。
答案 0 :(得分:65)
当您的运行时类路径与编译时类路径不同时,会发生这种情况。
编译应用程序时,一个类(在你的问题中名为SomeInterface
)作为一个类存在。
当您的应用程序在编译时运行时,SomeInterface
作为接口(而不是类)存在。
这会导致在运行时抛出IncompatibleClassChangeError
。
如果编译时类路径上的jar文件版本与运行时类路径上的版本不同,则这是常见的。
答案 1 :(得分:6)
很可能代码是针对库中的类编译的,然后将其更改为您运行的版本中的接口。
答案 2 :(得分:2)
我遇到了同样的问题。我在我的应用程序中使用了两个jar库。一个图书馆建立在另一个图书馆之上。
库A定义了顶级类和接口。图书馆B需要图书馆A.
这是库B中使用的一些代码的伪代码:
TheInterface instance = new TheClass();
instance.someMethod();
显然,库A比库B更新,TheInterface
不再包含someMethod
,但TheClass
仍然存在。解决这个问题的唯一方法是获取罐子的来源并手动更改这些东西(如果可能的话)。
答案 3 :(得分:1)
听起来像你做过
class MyClass extends SomeInterface
什么时候应该
class MyClass implements SomeInterface
我是对的吗?
编辑:哦,你说这是运行时错误而不是编译时错误?让我环顾四周...... 编辑2:看起来Jared有正确的答案。无论如何,尝试扩展接口实际上会在编译时提供“ no interface expected ”消息,而不是“找到的接口,但是类是预期的”错误。答案 4 :(得分:1)
这是在我运行maven build
时发生的。
从我可以收集到的信息(以及从Jared的answer那里)中获悉,原因是-我有效的pom.xml
中指定了同一个第三方jar的两个版本。一种版本是transitive dependency,另一种版本是我在本地pom.xml
中指定的。
因此,在编译时,它是指旧版本,而在运行时,它是指新版本。
我删除了在本地pom.xml
中指定的版本,并且可以正常工作。
当然,第3方打破了其版本之间的向后兼容性,并将类更改为接口,反之亦然。但是他们可以这样做。