私はとても混乱しています...
インターフェイスを直接実装するクラスがあります。
public class Device implements AutocompleteResult
{...}
ここに私が正しい変数を見ている証拠があります:
Object match = ...;
log.debug(match.getClass()); // Outputs 'Device'
log.debug(match.getClass().getInterfaces()[0]); // Outputs 'AutocompleteResult'
しかし、クラスのインスタンスをインターフェイスにキャストしようとすると、次のようになります。
AutocompleteResult result = (AutocompleteResult) match;
ClassCastExceptionが発生します。
ClassCastException: Device cannot be cast to AutocompleteResult
また、isAssignableFrom
はfalseを返し、理由はわかりません:
log.debug(AutocompleteResult.class.isAssignableFrom(Device.class));
doc から:
クラスまたはこのClassオブジェクトによって表されるインターフェースがか、指定されたClassパラメーターによって表されるクラスまたはインターフェースと同じか、スーパークラスまたはスーパーインターフェースです
クラスが実装するインターフェースにオブジェクトを常にキャストできるとは限りませんか?
ありがとう。
これは、2つの異なるクラスローダーがAutocompleteResult
という名前のクラスをロードした場合に発生する可能性があります。
これらの2つのクラスは、同じパッケージと名前(および実装/フィールド/メソッド)であっても、まったく異なるクラスとして扱われます。
これの一般的な原因は、ある種のプラグインシステムと、ベースクラスとプラグインクラスprovideの両方を同じクラスで使用している場合です。
この問題をチェックするには、 Class.getClassLoader()
によって返された値を両方の問題のあるクラス(つまり、Device
およびAutocompleteResult.class
)の結果。
AKA Javaの場合、Javaではないようです。
私は最近Play Framework 2.6.3でこの問題に遭遇しました、私を助けたのはこれでした: https://www.playframework.com/documentation/2.6.x/ThreadPools#Application-class-loader
同じ問題を抱えている可能性のある人のために、ここにこの情報を残します。
より明確にするために、役立つのは:
イーガーシングルトンにアプリケーションを注入し、そのクラスローダーを使用して、問題があったクラスをロードします。
より明確にするために
public class Module {
@Override
public void configure {
bind(TheClassLoaderLoader.class).asEagerSingleton()
public static class TheClassLoaderLoader {
@Inject
public TheClassLoaderLoader( Application application) {
ClassLoader classloader = application.classloader();
Class<?> interfaceClass = classloader.loadClass(InterfaceClass.class.getName());
classloader.loadClass(ImplementsInterfaceClass.class.getName()).asSubclass(interfaceClass);
ここの例 https://playframework.com/documentation/2.6.x/JavaDependencyInjection#Configurable-bindings
Environment
を使用すると、イライラするClassNotFoundException
が頻繁にスローされます
乾杯