Enrico Denti - RIFLESSIONE IN JAVA1
R IF LE SS IO N E (re flec tio n ) Il supp o rt o a ll a ri fle ss io n e c o n se n te a un p rog ra mm a d i is p ez io n a rs i ed op er a re su se st ess o .
T al e suppo rto co m re nd e: • la c la ss e Class n el p ac k ag e java.lang ; • l’ in te ro p ac k ag e java.lang.reflect c h e in tr odu ce le c la ss i
Method , Constructor e Field .
L a rif le ss ion e si u sa : • p er o tt en er e in fo rm az ion i su un a c la ss e e su i suo i m em b ri • p er o tt en er e in fo rm az ion i su ll e p rop rie tà e sug li ev en ti suppo rta ti d a un Ja v a B ea n • p er m an ipo la re ogg etti . In p ar ti co la re : • la c la ss e Field p er m ett e d i sc op rir e e im po st ar e v al o ri d i si ngo li ca m p i • la c la ss e Method c on se n te d i i nvo ca re m et od i • la c la ss e Constructor p er m ett e d i cr ea re nuov i ogg etti .
A lt re c la ss i acce ss o rie sono Modifier , Array e
ReflectPermission .
N B : i no mi d eg li ar go m en ti d ei m et od i non sono m em o rizza ti n ell a c la ss e, e qu ind i non sono rec up er ab ili v ia rif le ss ion e.
Enrico Denti - RIFLESSIONE IN JAVA
E S E M P IO - U n es em p io d i ri fle ss io n e Ipo te si : MostraClasse s i i nvo ca d all a li n ea d i co m ar go m en to ch e ra pp re se n ta il no m e d ell a c la ss e d a
import java.lang.reflect.*;
public class MostraClasse {
public static void main(String args[]) throws ClassNotFoundException {
Class c = Class.forName( args[0] ); // recupera un riferimento a quella classe // ---
if ( c.isInterface() ) // è un’interfaccia System.out.print(Modifier.toString( c.getModifiers() )+ c.getName() ); else // è una classe System.out.print(Modifier.toString( c.getModifiers() ) + " class " + c.getName() " extends " + c.getSuperclass().getName() // ---
Class[] interfacce = c.getInterfaces
if ((interfacce!=null)&&(interfacce.length>0)){ if ( c.isInterface() ) System.out.println(" extends "); else System.out.println(" implements "); }
for(int i=0; i<interfacce.length; i++){ if (i>0) System.out.print(", "); System.out.print(interfacce[i].getName()); }
// ---
Enrico Denti - RIFLESSIONE IN JAVA3
E S E M P IO - U n es em p io d i ri fle ss io n e (s eg u e)
// elenco dei metodi della classe System.out.println (" { "); System.out.println (" // Costruttori");
Constructor[] costruttori = c.getDeclaredConstructors (); for(int i=0; i<costruttori.length; i++) visualizza(costruttori[i]);
// ---
System.out.println (" // Campi dati");
Field[] campiDati = c.getDeclaredFields(); for(int i=0; i<campiDati.length; i++) System.out.print(" " + Modifier.toString( campiDati[i].getModifiers() ) + nomeTipo(campiDati[i].getType()) + " " + campiDati[i].getName() + ";" );
// ---
System.out.println (" // Metodi");
Method[] metodi = c.getDeclaredMethods(); for(int i=0; i<metodi.length; i++) visualizza(metodi[i]);
System.out.println (" } "); }
// --- metodi accessori ---
public static String nomeTipo(Class t){
String quadre= ""; while (t.isArray()) { quadre = quadre + "[]"; t = t.getComponentType(); } return t.getName() + quadre; }
Enrico Denti - RIFLESSIONE IN JAVA4
// --- segue metodi accessori ---
public static void visualizza(Member m){ // stampa la dichiarazione di un metodo // o di un costruttore
Class tipoRit = null; Class[] parametri; Class[] eccezioni;
if (m instanceof Method) { // è un metodo Method metodo = (Method) m; tipoRit = metodo. getReturnType(); parametri = metodo. getParameterTypes(); eccezioni = metodo. getExceptionTypes(); } else { // è un costruttore Constructor costr = (Constructor) m; parametri = costr.getParameterTypes(); eccezioni = costr.getExceptionTypes(); }
System.out.print(" " + Modifier.toString( m.getMo difiers( )) + " " + (tipoRit!=null ? nomeTipo(tipoRit) + " " : "") + m.getName() + "(" );
for(int i=0; i<parametri.length; i++){ if (i>0) System.out.print(", "); System.out.print(nomeTipo(parametri[i])); }
System.out.print (")");
if (eccezioni.length>0) System.out.print(" throws ");
for(int i=0; i<eccezioni.length; i++){ if (i>0) System.out.print(", "); System.out.print(nomeTipo(eccezioni[i])); }
System.out.println(" ;"); }}
Enrico Denti - RIFLESSIONE IN JAVA5
E S E M P IO - U n es em p io d i ri fle ss io n e - U S O Invo caz ion e:
java MostraClasse classeDaIspezionare
A d es em p io :
java MostraClasse MostraClasse
O u tpu t:
public class MostraClasse extends java.lang.Object {// Costruttoripublic MostraClasse();// Campi dati// Metodipublic static void main(java.lang.String[]) throwsjava.lang.ClassNotFoundException;public static java.lang.String nomeTipo(java.lang.Class);public static void visualizza(java.lang.reflect.Member);}
Enrico Denti - RIFLESSIONE IN JAVA
INV O CA Z IO N E IND IR ETT A D I M ET O D I
S ebbn e Ja v a non con se n ta d i p ass ar e m et od i co m e l’ an al ogo d ei “pun ta to ri a fun zi on e” d el C ), la ri fle te d i i n vo ca re ind ire tt a m en te un m et o d o p a ss a to
A tt en zi on e: qu es ta tec n ica non è m o lt o effi ci en te , qu so lo se l’ eff ic ie n za non è un p rob le m a (e s. g es ti on e
L o sc h em a d i i n vo ca zi o n e ind ire tt a è
res = m.invoke(oggettoTarget ,
dov e m è un ’is ta n za d i Method , args è un arr ay d i ra pp re se n ta no g li ar go m en ti d a p ass ar e a l m et odo ,
Object c h e ra pp re se n ta il ris u lt at o d el m et odo .
N B : invoke () è in g ra do d i conv er ti re a u to m ati ca p rimiti v i n ei co rr is pond en ti ti p i “w ra pp er ” e v ice v er po te r ch ia m ar e a n ch e m et od i con p ar am et ri int , float
P ro b le m a : co m e o tt en er e l’ ogg ett o m , d i cl a ss e Method ch e rapp re se n ta il m et odo da ch ia m a
S o li ta m en te , l’ ogg ett o m et o d o v ie n e rec up er a to ch ia m a ta a getMethod() :
m = c.getMethod( nomeMetodo , parametri
dov e c è un ’is ta n za d i Class c h e ra pp re se n ta la c la g ett o ta rg et su cu i il m et odo v err à c h ia m at o , nomeMetodo
String c h e c on ti en e il no m e d el m et odo , e parametri a rr a y d i Class c h e ra pp re se n ta la li st a d ei pa ra m et m et odo . A d es em p io :
Class parametri[] = {int.class, int.class}; m = c.getMethod(" setLocation", parametri);
Enrico Denti - RIFLESSIONE IN JAVA7
INV O CA Z IO N E IND IR ETT A D I M ET O D I
L o sc h em a tip ic o
Object res=null;
// recupero della classe dell’oggetto target
Class c = ogg.getClass() ; // preparazione array dei parametri formali
Class [] parametriFormali; ...
// recupero del metodo
Method m = null; try { m = c.g etMethod( nomeMetodo, parametriFormali); } catch (NoSuchMethodException e){}
// predisposizione array degli parametri attuali
Object [] parametriAttuali; ...
// invocazione del metodo
try { res = m.invoke(ogg, parametriAttuali); } catch(IllegalAccessException e){} catch(InvocationTargetException e){}
dov e: • ogg è l’ ogg ett o (ta rg et ) su cu i v a invo ca to il m et odo • nomeMetodo è il no m e d el m et odo d a invo ca re • parametriFormali è l’ arr ay d i Class c h e c on ti en e i p ar am at ri fo rm a li • parametriAttuali è l’ arr ay d i Object c h e c on ti en e i p ar am at ri a tt u a li
N B : se il m et odo d a invo ca re è static , l’ ogg ett o ta rg et ogg v ie n e igno ra to , e può (a n zi , dov re bb e) ess er e null .
Enrico Denti - RIFLESSIONE IN JAVA8
E S E M P IO 1 - In vo ca zi o n e d i m et o d i se n za a rgo m en ti
import java.lang.reflect.*; import java.awt.Point;
public class ProvaInvoke1 {
public static Object chiama0(Object ogg, String nomeMetodo) { // senza parametri Object res = null; Class c = ogg.getClass ();
Class parametriFormali[] = null; // senza param System.out.println ("Calling "+nomeMetodo+"()");
Method m = null; try { m = c.getMethod(nomeMetodo, parametriFormali); } catch (NoSuchMethodException e){ System.err.println("Metodo inesistente"); }
Object[] parametriAttuali = null; try { res = m.invoke(ogg, parametriAttuali); } catch(InvocationTargetException e){ System.err.println ("Target illegale"); } catch(IllegalAccessException e){ System.err.println ("Accesso illegale"); } return res; }
public static void main(String args[]) { Point p = new Point (10,20); Double x = (Double) chiama0(p," getX"); Double y = (Double) chiama0(p," getY"); System.out.println (" X = " + x + ", Y = " +y); }}
Enrico Denti - RIFLESSIONE IN JAVA9
IL P R O BLE M A C O N invoke () e getmethod()
M en tr e invoke() è in g ra do d i conv er ti re a u to m ati ca m en te i ti p i p rimiti v i ( int , float ,… ) n ei co rr is pond en ti ti p i “w ra p - p er ” ( Integer , Float ,… ) e v ice v er sa , getMethod() n o n lo fa : i p a ra m et ri fo rm a li d evo n o co rr is po n d er e e sa tt a - m en te a l m et odo ce rca to , alt rim en ti ess o non v err à tr ov at o .
Q u es to h a co m e c o n se g u en za un a d iff ic o lt à n ell ’in vo ca re m et od i co n pa ra m et ri d i ti p i p rimiti vi , i n qu an to : • invoke() p re te nd e c h e i p a ra m et ri a tt u a li si a n o Object (l’ arr ay ch e li con ti en e è un arr ay d i Object ), e i ti p i p ri m iti vi non lo sono → o cc o rr e p ass ar e i co rr is pond en ti ti p i “w ra pp er ” (c h e invoke() c onv er ti rà , p er alt ro , au to m ati ca m en te ) • getMethod() p re te nd e in v ece c h e i p a ra m et ri fo rm a li si a n o p er fe tt a m en te c o rr is po n d en ti a q u elli d ic h ia ra ti n el m et odo → ti p i p rimiti v i e ti p i w ra pp er sono d ive rs i!
C iò re nd e im p o ss ib il e scr iv ere un a fun zi o n e call () g en er a le , in g ra d o d i ch ia m a re q u a lun q u e m et o d o .
È p er ò po ss ib il e: • invo ca re qu al unqu e m et odo (a n ch e c on te n en te ti p i p rimiti v i) ch ia m ando getMethod() “ ad ho c” → E S E M P IO 2 • sc riv er e un a fun zi on e call() “ qu as i g en er al e” , att a a invo ca re qu al unqu e m et odo c h e non u si ti p i p ri m iti vi → E S E M P IO 3
F o rtun at am en te , p er qu as i t u tti i m et od i Ja v a c h e u sa no ti p i p rimiti v i es is te an ch e una ve rs ion e c h e li i n cap su la in un qua lc h e ogg ett o . A d es em p io , la c la ss e Point d ef in is ce • si a il m et odo void setLocation(int, int) • si a il m et odo void setLocation(Point)
Enrico Denti - RIFLESSIONE IN JAVA
E S E M P IO 2 - In vo ca zi o n e d i m et o d o co n du e a rgo
import java.lang.reflect.*; import java.awt.Point;
public class ProvaInvoke2 {
public static Object chiama1(Object ogg, Method m , Object args[] ) { Object res = null;
try { res = m.invoke(ogg, args); }
catch(InvocationTargetException e){ System.err.println ("Target illegale"); } catch(IllegalAccessException e){ System.err.println ("Accesso illegale"); } return res; }
public static void main(String args[]) { Point p = new Point (10,20); Method getX = null, getY = null, sL = null;
try { // due modi alternativi getX = p.getClass().getMethod("getX",null); getY = Point.class.getMethod("getY",null); } catch (NoSuchMethodException e) {}
System.ou t.println (" X = " + x + ", Y = " +y);
Class intintArgs[] = {int.class,int.class}; try {
sL=Point.getMethod("setLocation",intintArgs);
} catch (NoSuchMethodException e) {}
Integer argomenti[] = { new Integer (30), new Integer(40) };
chiama1(p,setLoc, argomenti); Double x = (Double) chiama1(p, getX, null); Double y = (Double) chiama1(p, getY, null); System.out.println (" X = " + x + ", Y = " +y); }}
Enrico Denti - RIFLESSIONE IN JAVA11
E S E M P IO 3 - In vo ca zi o n e d i m et o d o co n un a rgo m en to Point
import java.lang.reflect.*; import java.awt.Point;
public class ProvaInvoke3 {
public static Object chiama(Object ogg, String metodo, Object args[]) {
Object res = null; Class c = ogg.getClass (); Class parametriFormali[] = null; int argNum = 0;
if (args==null) { System.out.println ("Calling "+ metodo +"()"); } else { System.out.print ("Calling " + metodo + "(");
argNum = args.length; parametriFormali = new Class[argNum]; for (int i=0; i<argNum-1; i++) { parametriFormali[i] = args[i].getClass(); System.out.print(args[i].get Class().getName() + ","); } parametriFormali[argNum-1] = args[argNum-1].getClass(); System.out.println( args[argNum -1]. getClass().getName() +")"); }
Method m = null; try { // trova solo metodi senza tipi primitivi m = c.getMethod(metodo, parametriFormali); } catch (NoSuchMethodException e){ System.err.println ("Metodo inesistente"); }
// segue...
Enrico Denti - RIFLESSIONE IN JAVA12