sabato 14 febbraio 2009

Java Reflection

Java Reflection

La reflection permette di esaminare o modificare il comportamento run-time di un applicazione java  eseguita nella JVM. Questa proprietà avanzata è applicata, tra l'altro, nei seguenti casi:
  • Caratteristiche di estensibilita: un'applicazione può fare uso di classi esterne definite dall'utente, creando istanze si esse usando il "fully-qualified" path.
  • Ambienti di sviluppo visuale (IDE): generalmente gli ambienti di sviluppo visuale (p.e. NetBeans o Eclipse), che richiedono la presenza di un 'browser' di classi,  per aiutare gli sviluppatori a scrivere codice corretto e semplice fanno largo uso della reflection, molto utile quando di vuole enumerare i membri di una classe.
  • Debug e test: i debugger necessitano di conoscere i membri privati di una classe, per determinarne il valore in un determinato istante.

La reflection è uno strumento molto potente ma che dovrebbe essere usato con cautela; in genere se è possibile raggiungere un obiettivo senza l'uso della reflection, è preferibile non farne uso. In particolare è necessario tener presente i seguenti svantaggi:
  • Overhead delle prestazioni: considerando che la reflection comporta la risoluzione dei tipi dinamicamente, alcune ottimizzazioni fatte dalla JVM non possono essere effettuate, per cui l'uso della reflection è sconsigliato nelle sezioni di codice che sono richiamate frequentemente nelle applicazioni performance-sensitive.
  • Restrizioni di sicurezza: la reflection richiede permessi di sicurezza che non sono presenti quando l'esecuzione di un applicazione avviene in presenza di un security manager. Di questo particolare bisogna tener conto per esempio nello sviluppo di un'Applet.
  • Esposizione dei membri interni: considerando che la reflection permette di effettuare operazioni 'illegali', per esempio accesso ai campi e metodi privati di un oggetto, si potrebbe rischiare di compromettere la portabilità del codice. In particolare viene eliminato il concetto di astrazione con conseguenti problemi in seguito ad upgrade della piattaforma.

Attraverso la reflection è possibile conoscere a run-time tutti i metodi di una classe ed eventualmente invocarne uno. Il seguente listato permette di invocare il metodo di una classe con opportuni parametri, senza che siano noti a priori il numero e tipo dei parametri:


package test;

import java.lang.reflect.*;
import java.util.Hashtable;

public class ReflectionTest {

    public static void main(String args[])
            throws Exception {
        Class classe = Class.forName(args[0]);
        String methodName = args[1];
        Method[] methods = classe.getDeclaredMethods();
        Hashtable<String, Method> methodHashtable =
                new Hashtable<String, Method>();
        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];
            String name = method.getName();
            methodHashtable.put(name, method);
        }
        Method m = methodHashtable.get(methodName);
        Class[] paramTypes = m.getParameterTypes();
        if (paramTypes.length != args.length - 2) {
            System.out.println("Num. parametri errato");
            System.exit(0);
        }
        int paramNum = paramTypes.length;
        Object[] params = new Object[paramNum];
        for (int j = 0; j < paramNum; j++) {
            Class type = paramTypes[j];
            Constructor c =
                    type.getConstructor(String.class);
            params[j] = c.newInstance(args[j + 2]);
        }
        System.out.println(m.invoke(classe.newInstance(), params));
    }
}

class ReflectionTestClass {

    public Integer sum(Integer i, Integer j) {
        return i + j;
    }
}


Il main si richiama con la sintassi "java ReflectionTest <nomeClasse> <nomeMetodo> <parametro1> <parametro2> ...", per esempio "java test.ReflectionTest test.ReflectionTestClass  sum 2 3"

Nessun commento: