2011-11-07 17 views
29

io sono molto confuso ...non può lanciare a interfaccia implementata

ho una classe che implementa l'interfaccia direttamente:

public class Device implements AutocompleteResult 
{...} 

Ecco la prova che sto guardando in alto a destra variabili:

Object match = ...; 
log.debug(match.getClass()); // Outputs 'Device' 
log.debug(match.getClass().getInterfaces()[0]); // Outputs 'AutocompleteResult' 

Eppure, quando provo a lanciare un'istanza della classe per l'interfaccia:

AutocompleteResult result = (AutocompleteResult) match; 

Ricevo una ClasseCastException!

ClassCastException: Device cannot be cast to AutocompleteResult 

Inoltre, isAssignableFrom restituisce false e non sono sicuro perché:

log.debug(AutocompleteResult.class.isAssignableFrom(Device.class)); 

dal doc:

determina se il classe o interfaccia rappresentato da questa classe l'oggetto è o uguale a, oppure è una superclasse o superinterf asso di, la classe o l'interfaccia rappresentata dal parametro Class specificato.

Non dovrei essere sempre in grado di trasmettere un oggetto a un'interfaccia le sue implementazioni di classe?

Grazie.

+0

Sì, si dovrebbe! (e non dovresti nemmeno aver bisogno del cast esplicito.) Pubblica un codice di esempio autosufficiente che mostri il problema. –

risposta

54

Ciò può accadere se due diversi classloader caricano una classe denominata AutocompleteResult.

Queste due classi vengono quindi considerate come classi completamente diverse, anche se hanno lo stesso pacchetto e nome (e persino implementazione/campi/metodi).

Una causa comune per questo è se si utilizza una sorta di sistema di plugin e sia le classi di base e le classi di plug-in forniscono la stessa classe.

Per verificare questo problema stampare il valore restituito da Class.getClassLoader() sia sulle classi di offendere (vale a dire la classe dell'interfaccia implementata da Devicee il risultato di AutocompleteResult.class).

+1

wow, grazie! stavo letteralmente strappando i capelli a questo. cercherò di risolvere il problema del caricamento di classe ora ... – pstanton

+3

+1: prova 'log.debug (match.getClass(). getInterfaces() [0] .getClassLoader()); log.debug (AutocompleteResult.class.getClassLoader()) ' –

+0

Il mio problema era che avevo la classe importata sbagliata e questo mi ha aiutato a determinare che:' Class [] interfaces = match.getClass(). getInterfaces(); for (int i = 0; i toobsco42

0

AKA quando Java apparentemente non Java.

mi ha colpito questo problema recentemente con 2.6.3 Riproduzione quadro, quello che mi ha aiutato è stato questo: https://www.playframework.com/documentation/2.6.x/ThreadPools#Application-class-loader

lascio questo info qui per le persone che potrebbero avere lo stesso problema.

per renderlo più chiaro, ciò che aiuta è:

iniezione Applicazione su un Singleton Eager e quindi utilizzando il suo programma di caricamento classe per caricare le classi che ho avuto problemi con.

per renderlo più chiaro

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); 

L'esempio qui https://playframework.com/documentation/2.6.x/JavaDependencyInjection#Configurable-bindings

che utilizza Environment spesso getta una frustrante ClassNotFoundException

Acclamazioni

Problemi correlati