2010-05-07 13 views

risposta

7

I framework Mock non istanziano le interfacce, costruiscono classi che li implementano al volo in fase di runtime. Potresti trovare this javadoc enlightening per quello che vuoi fare!

2

Non è possibile creare un'istanza di una classe che non è stata specificata completamente.

Per illustrare, chiamando newInstance() su una classe di tipo Class<Object> sarebbe sicuramente creare un oggetto, ma chiamando newInstance() su una classe di tipo Class<?> avrebbe lasciato il compilatore chiedendosi quale classe fuori di tutto l'universo di possibilità che dovrebbe costruire.

Solo perché si è ristretto il campo giù un po ', specificando che, invece di appena ?, si desidera un ? che si estende Annotation non significa che hai effettivamente nominato una classe particolare di costruire. ? extends Annotation significa semplicemente "una classe che estende Annotation" Senza nominare la classe esatta, ClassLoader non riesce a capire quale costruttore chiamare, poiché non esiste un limite al numero di classi che potrebbero estendersi Annotation.

EasyMock non crea un'istanza di interfacce. Non ho familiarità con il framework, ma probabilmente istanzia java.lang.Object (s) che estendono l'interfaccia desiderata, o crea un'istanza di una sorta di classe framework "dietro le quinte" che è stata generata con una clausola "implements interface" nella definizione della classe. Le interfacce non hanno un costruttore predefinito.

+0

Credo che EasyMock usi CGLIB. Mockito usa CGLIB. CGLIB è una libreria che ti consente di creare un oggetto proxy. È più veloce del proxy Java poiché crea/manipola bytecode. – mjlee

+0

Sembra che EasyMock generi una classe con un nome simile a $ Proxy0. Il simbolo $ rappresenta in genere un nome di classe interno/generato e lo 0 è probabilmente il numero di classe del mocked interno secondo l'architettura interna di EasyMock. La modalità così semplice crea ancora una classe, non un'interfaccia; tuttavia, crea una classe che implementa ovviamente l'interfaccia. –

+0

Questa risposta è semplicemente una sciocchezza. Esistono tipi di caratteri jolly sulla JVM ma non rappresentano mai un tipo concreto. Qualsiasi? -pointer si riferisce sempre a un tipo concreto. –

7

Grazie a Affe per avermi indirizzato nella giusta direzione - avrei commentato la sua risposta ma poi non sarei stato in grado di formattare la soluzione:

Annotation annotation = (Annotation) Proxy.newProxyInstance(
    clazz.getClassLoader(), 
    new Class[] { Annotation.class }, 
    new InvocationHandler() { 
    @Override public Object invoke(Object proxy, Method method, Object[] args) { 
     return clazz; // only getClass() or annotationType() should be called. 
    } 
    });
funziona come un incantesimo.

+4

Non riesco a capire quale possibile _buona_ questa istanza di Annotazione rotta potrebbe farti. È come se avessi chiesto un hamburger e ottenuto una fotocopia di una vecchia fotografia in bianco e nero di un panino al prosciutto. Spiegare? –

+0

Sto lavorando con il codice Guice che si occupa di annotazioni vincolanti. Tranne per '@ Named', solo' annotationType() 'e forse' getClass() 'vengono mai chiamati sul passaggio di' Annotation' al metodo che sto chiamando. Quindi, finché il mio 'Annotation' può imitare quei metodi, funzionerà bene. – Steve

+0

@Steve 'getClass()' non viene passato a 'InvocationHandler' e restituisce' Proxy.class'. Ma probabilmente vuoi 'toString()' per il debugger. – Brainlag

0

Se si conosce il tipo di annotazione in fase di compilazione, è sufficiente creare una classe che implementa l'annotazione come se fosse un'annotazione normale. Vedi anche this answer.

Problemi correlati