コードから奇妙なランタイムエラーが発生します:
"Found interface [SomeInterface] but class was expected"
これはどのように起こりますか?インターフェイスをインスタンス化するにはどうすればよいですか?
更新:(いくつかの回答に応じて)同じライブラリセットに対してコンパイルして実行していますが、 amGuice を使用して、この特定のインターフェイスのプロバイダーを挿入します。
実装をインターフェースにバインドすると、問題は解決しました(@ImplementedByアノテーションでは不十分だったようです)。
Guiceが実際にインターフェースをインスタンス化するための仕組みにもっと興味がありました。
これは、ランタイムクラスパスがコンパイル時クラスパスと異なる場合に発生します。
アプリケーションがコンパイルされたとき、クラス(質問ではSomeInterface
という名前)がクラスとして存在していました。
アプリケーションがコンパイル時に実行されている場合、SomeInterface
は(クラスではなく)インターフェイスとして存在します。
これにより、実行時にIncompatibleClassChangeError
がスローされます。
これは、コンパイル時のクラスパスと実行時のクラスパスに異なるバージョンのjarファイルがある場合によく発生します。
ほとんどの場合、コードはライブラリ内のクラスに対してコンパイルされ、実行対象のバージョンのインターフェイスに変更されました。
私も同じ問題を抱えていました。アプリケーションで2つのjarライブラリを使用しています。 1つのライブラリは他のライブラリの上に構築されます。
ライブラリAは、トップクラスとインターフェイスを定義します。ライブラリBにはライブラリAが必要です。
これは、ライブラリBで使用されているいくつかのコードの擬似コードです。
TheInterface instance = new TheClass();
instance.someMethod();
どうやらライブラリAはライブラリBよりも新しく、TheInterface
にはsomeMethod
が含まれていませんが、TheClass
には含まれています。これを修正する唯一の方法は、いずれかのjarのソースを取得し、これらを手動で変更することです(可能な場合)。
これは、私がmaven build
を実行していたときに起こりました。
理由として私が収集できたものから(およびJaredの answer から)-私の効果的なpom.xml
で指定された同じサードパーティjarの2つのバージョンがありました。 1つのバージョンは 推移的な依存関係 として提供され、もう1つのバージョンはローカルのpom.xml
で指定されました。
したがって、コンパイル時には古いバージョンを参照し、実行時には新しいバージョンを参照していました。
ローカルのpom.xml
で指定されたバージョンを削除しましたが、機能しました。
もちろん、サードパーティはバージョン間の下位互換性を壊し、クラスをインターフェイスに変更したり、その逆を行ったりしていました。しかし、彼らはそうするのは自由です。
あなたがしたように聞こえます
class MyClass extends SomeInterface
それが実際にあるべきとき
class MyClass implements SomeInterface
私は正しいですか?
編集:ああ、あなたはそれがランタイムエラーであり、コンパイル時エラーではないと言いますか?少し見てみましょう...
編集2:Jaredが正しい答えを持っているようです。とにかく、インターフェースを拡張しようとすると、実際にはコンパイル時に "ここではインターフェースは予期されていません"メッセージが表示されます。 "インターフェースは見つかりましたがクラスが予期されていました"エラーではありません。