web-dev-qa-db-ja.com

Javaエラー:インターフェースが見つかりました...しかしクラスが必要でした

コードから奇妙なランタイムエラーが発生します:

"Found interface [SomeInterface] but class was expected"

これはどのように起こりますか?インターフェイスをインスタンス化するにはどうすればよいですか?

更新:(いくつかの回答に応じて)同じライブラリセットに対してコンパイルして実行していますが、 amGuice を使用して、この特定のインターフェイスのプロバイダーを挿入します。

実装をインターフェースにバインドすると、問題は解決しました(@ImplementedByアノテーションでは不十分だったようです)。

Guiceが実際にインターフェースをインスタンス化するための仕組みにもっと興味がありました。

34
levik

これは、ランタイムクラスパスがコンパイル時クラスパスと異なる場合に発生します。

アプリケーションがコンパイルされたとき、クラス(質問ではSomeInterfaceという名前)がクラスとして存在していました。

アプリケーションがコンパイル時に実行されている場合、SomeInterfaceは(クラスではなく)インターフェイスとして存在します。

これにより、実行時にIncompatibleClassChangeErrorがスローされます。

これは、コンパイル時のクラスパスと実行時のクラスパスに異なるバージョンのjarファイルがある場合によく発生します。

72
Jared

ほとんどの場合、コードはライブラリ内のクラスに対してコンパイルされ、実行対象のバージョンのインターフェイスに変更されました。

6
starblue

私も同じ問題を抱えていました。アプリケーションで2つのjarライブラリを使用しています。 1つのライブラリは他のライブラリの上に構築されます。

ライブラリAは、トップクラスとインターフェイスを定義します。ライブラリBにはライブラリAが必要です。

これは、ライブラリBで使用されているいくつかのコードの擬似コードです。

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

どうやらライブラリAはライブラリBよりも新しく、TheInterfaceにはsomeMethodが含まれていませんが、TheClassには含まれています。これを修正する唯一の方法は、いずれかのjarのソースを取得し、これらを手動で変更することです(可能な場合)。

2
Mark Jeronimus

これは、私がmaven buildを実行していたときに起こりました。

理由として私が収集できたものから(およびJaredの answer から)-私の効果的なpom.xmlで指定された同じサードパーティjarの2つのバージョンがありました。 1つのバージョンは 推移的な依存関係 として提供され、もう1つのバージョンはローカルのpom.xmlで指定されました。

したがって、コンパイル時には古いバージョンを参照し、実行時には新しいバージョンを参照していました。

ローカルのpom.xmlで指定されたバージョンを削除しましたが、機能しました。

もちろん、サードパーティはバージョン間の下位互換性を壊し、クラスをインターフェイスに変更したり、その逆を行ったりしていました。しかし、彼らはそうするのは自由です。

1
Pradeep Anchan

あなたがしたように聞こえます

class MyClass extends SomeInterface

それが実際にあるべきとき

class MyClass implements SomeInterface

私は正しいですか?

編集:ああ、あなたはそれがランタイムエラーであり、コンパイル時エラーではないと言いますか?少し見てみましょう...

編集2:Jaredが正しい答えを持っているようです。とにかく、インターフェースを拡張しようとすると、実際にはコンパイル時に "ここではインターフェースは予期されていません"メッセージが表示されます。 "インターフェースは見つかりましたがクラスが予期されていました"エラーではありません。

1
Michael Myers