Newsgroup: it.comp.java
Titolo: Capire se un metodo appartiene ad una interfaccia

Ho un oggetto di classe MiaClasse.
MiaClasse implementa una data interfaccia (Supponiamo chiamata
MiaInterfaccia)
Tramite introspector ottengo un oggetto di classe
java.lang.reflect.Method che mi descrive un metodo della classe.
C'e' un modo per scoprire se tale metodo fa parte dell'interfaccia
MiaInterfaccia, o devo confrontare nome e parametri per vedere se ha
la stessa signature di un metodo dell'interfaccia?
Andrea

 la stessa signature di un metodo dell'interfaccia?
Non vedo altra soluzione utilizzando la reflecion.
Quello che non mi convince è il fatto che è una logica "contro natura", 
le interfacce esistono proprio perchè le signature dei metodi sono 
conosciute al programmatore per definizione.


In effetti è una situazione un pò strana. Io ho un oggetto che 
implementa alcune interfacce. Ad un certo punto ho bisogno di cambiare 
il comportamento di quell'oggetto (proprio di quell'istanza) facendo in 
modo che i metodi di una di queste interfacce siano delegati ad un altro 
oggetto. Forse se scrivo del codice e' meglio:
public interface MiaInterfaccia {
   void mioMetodo();
}
public interface AltraInterfaccia {
   ...
}
public interface InterfacciaCompleta
             extends MiaInterfaccia, AltraInterfaccia {
}
public class MiaClasse implements MiaInterfaccia {
   public void mioMetodo() {
     // Fai qualcosa
   }
   public void altroMetodo() ...
}
public class AltraClasse implements MiaInterfaccia {
   public void mioMetodo() {
     // Fai qualcosa di diverso
   }
}
A questo punto ho un'istanza di MiaClasse (chiamiamola mioOggetto) e una 
di AltraClasse (altroOggetto) e ho bisogno di costruire un oggetto che 
presenti l'interfaccia InterfacciaCompleta che si comporti come se fosse 
mioOggetto tranne che per i metodi definiti in MiaInterfaccia. Quando si 
invoca uno di questi metodi l'oggetto di cui ho bisogno si deve 
comportare come se fosse altroOggetto.
Per far questo costruisco un proxy (java.lang.reflect.Proxy):
InterfacciaCompleta proxy = (InterfacciaCompleta)Proxy.newProxyInstance(
                        MiaInterfaccia.class.getClassLoader(),
                        new Class[] {InterfacciaCompleta.class},
                        invocationHandler);
invocationHandler deve essere un istanza dell'interfaccia 
InvocationHandler che definisce il seguente metodo:
public Object invoke(Object proxy,
                      Method method,
                      Object[] args)
Tale metodo viene invocato ogni volta che si invoca un metodo 
sull'oggetto proxy passando come argomenti l'oggetto proxy, il metodo 
chiamato e gli argomenti.
Il corpo del metodo, nel mio caso dovrebbe essere:
public Object invoke(Object proxy,
                      Method method,
                      Object[] args) {
   if(/**** method è un metodo di MiaInterfaccia ****/)
     return method.invoke(altroOggetto, args);
   else
     return method.invoke(mioOggetto, args);
}
Il problema è che non so come scrivere in modo "decente" la condizione 
dell'if.
Tenete presente che nel mio caso non posso modificare ne' estendere 
(dato che non sono io a costruire l'istanza di mioOggetto) MiaClasse e 
che chi utiliza il proxy non deve sapere di utilizzare qualcosa che non 
e' una semplice istanza di InterfacciaCompleta. Quindi non ho trovato 
alternative all'utilizzo del proxy (tranne, forse, utilizzare l'AOP, ma 
non sono ferrato in materia e comunque non e' il caso di utilizzarlo nel 
progetto a cui sto lavorando).
Andrea


Con le attuali API di Reflection mi sa che devi proprio
confrontare nome e signature.
Non è poi troppo difficile,
basta usare il methodo statico methodInInterface qui di seguito esposto
   static boolean sameSignature(Method a, Method b) {
     Class[]ac = a.getParameterTypes();
     Class[]bc = b.getParameterTypes();
     if(ac.length != bc.length)
       return false;
     for(int i=0; i<ac.length; i++)
       if(ac[i] != bc[i])
         return false;
     return true;
   }
   static boolean methodInInterface(Method m, Class ifc) {
     if(!ifc.isInterface())
       return false;
     Method[]ifcm = ifc.getDeclaredMethods();
     for(int i=0; i<ifcm.length; i++)
       if(m.getName().equals(ifcm[i].getName()))
         return sameSignature(m, ifcm[i]) &&
           ifcm[i].getReturnType().isAssignableFrom(m.getReturnType());
     return false;
   }
Nel mio esempio ho anche confrontato la compatibilità
dei valori di ritorno dei due metodi.
- Dario

 la stessa signature di un metodo dell'interfaccia?
Credo che tu possa ottenere anche l'array dei metodi della tua interfaccia.
A quel punto guardi se nell'array ce un oggetto method uguale al tuo
(quindi con equals()).
Ciao
Matteo
-- 
chi sono e soprattutto chi non sono:
http://www.ilnomedeldominio.it
un piccolo programma per studenti universitari:
http://inutility.ilnomedeldominio.it/imsv/

 uguale al tuo (quindi con equals()).
Purtroppo non dovrebbe, perche' la declaring class fa parte del metodo e 
ovviamente e' differente tra una classe e un'interfaccia che quella classe 
implementa.