PDA

View Full Version : [JAVA] Reflection


ceccoggi
04-03-2008, 11:01
Salve a tutti, vi spiego qual'è il mio problema.
Devo creare un metodo generico che leggendo da un file xml degli elementi, ricerchi all'interno della classe xxx se sono presenti tali parametri e me li cambi secondo il valore corrispondente all'elemento sul file xml.

vi faccio un esempio

XML file:

<classeA>
<param1>pinco</param1>
<param2>pallino</param2>
</classeA>


metodo java:

Pseudocodice

Ciclo sul file XML
Leggo il tag di ogni elemento
Cerco nella classe java che voglio modificare se esiste un parametro uguale al tag dell'elemento cercato sul file xml.
Se c'è modifico il valore di tale parametro con quello letto nell'xml.


Mi è stato consigliato di usare Java.Reflection, ma essendo la prima volta che ne sentivo parlare e la usavo, mi da un'errore nel test...
Di seguito il mio codice java scritto (premettendo che i metodi di navigazione nel tree xml sono personalizzati, presi da una mia classe funzionante)

Class c = this.getClass();
Field campo;
for(int i=0; i<xmlroot.size(); i++){
if((campo=c.getField(xmlroot.getElement(i).getTag()))!=null)
campo.set(campo, xmlroot.getElement(i).getValue());

else{
setMailHost("mailhost");
setMyTo("Marco");
}
}


L'errore che mi da è che leggendo dall'xml il tag "mailHost", dovrebbe cercare all'interno della classe la variabile "mailHost"..e mi dice che non esiste..quando esiste benissimo, quindi deduco di aver sbagliato qualcosa nel codice..

QUalcuno può aiutarmi?

Tnx

TuX2K6
04-03-2008, 14:07
Se non hai le già classi e l'XML è correlato di XSD ti conviene usare JAXB che ti crea le classi a partire dall'XSD e puoi a partire dall'XML ottenere una collection di oggetti già valorizzati.

Molto meglio che rifarsi tutto a mano ;)

gugoXX
04-03-2008, 14:21
L'errore che mi da è che leggendo dall'xml il tag "mailHost", dovrebbe cercare all'interno della classe la variabile "mailHost"..e mi dice che non esiste..quando esiste benissimo, quindi deduco di aver sbagliato qualcosa nel codice..

QUalcuno può aiutarmi?

Tnx

Se la reflection in Java funziona come in C#, puoi accedere solo ai membri pubblici.

isAlreadyInUse
04-03-2008, 14:32
public static void setProperty(String name, Object target, Object value) {
Method metodo = null;
String nameToUpperCase = checkCase(name);
try {
metodo = target.getClass().getMethod("set" + nameToUpperCase, new Class[] {value.getClass()});
}
catch (NoSuchMethodException e) { }
if (metodo != null)
try {
metodo.invoke(target, new Object[] {value});
}
catch (Exception ecc) { }
}

ceccoggi
04-03-2008, 14:44
public static void setProperty(String name, Object target, Object value) {
Method metodo = null;
String nameToUpperCase = checkCase(name);
try {
metodo = target.getClass().getMethod("set" + nameToUpperCase, new Class[] {value.getClass()});
}
catch (NoSuchMethodException e) { }
if (metodo != null)
try {
metodo.invoke(target, new Object[] {value});
}
catch (Exception ecc) { }
}


Non è detto che io abbia un getter o un setter..quindi vorrei modificare direttamente il campo senza usare il metodo setter..

ceccoggi
04-03-2008, 16:23
metodo = target.getClass().getMethod("set" + nameToUpperCase, new Class[] {value.getClass()});



Pur usando questo metodo, cosa dovrei mettere come "value", se alla fine il valore a cui voglio settare il mio parametro lo leggo dall'xml (e lo ottengo tramite xmlroot.getElement(i).getValue()) ?

ceccoggi
05-03-2008, 09:59
please, nessuno riesce a aiutarmi?!?

tnx

ceccoggi
05-03-2008, 15:36
Ragazzi sono giunto a una conclusione..pero' non e' il risultato che volevo, vediamo se qualcuno riesce a aiutarmi...

Dunque, volendo creare una classe di inizializzazione di queste variabili (che leggerei da xml) vorrei non dover sapere a priori il nome della classe su cui voglio lavorare (deve poterla leggere sempre dall'xml e sara' per l'appunto il tag root del mio xml).

quindi questo e' il codice che vorrei utilizzare (ma che non funziona, nel senso pare non modifichi un bel niente..


Class c = Class.forName(prefix+"."+checkCase(xmlroot.getTag()));
Object item = this.getItem(xmlroot.getTag());
Method metodo = null;
String stringa;

for(int i=0; i<xmlroot.size(); i++){
if((campo=c.getField(xmlroot.getElement(i).getTag()))!=null)
{
stringa = xmlroot.getElement(i).getValue();
metodo = c.getMethod("set" + checkCase(xmlroot.getElement(i).getTag()),new Class[] { stringa.getClass() });
metodo.invoke(item, new Object [] { stringa });

OPPURE

campo.set(item, stringa); dovrebbe fare la stessa cosa che metodo.invoke, ossia modificarmi il campo
}
}


.....




dove getItem e'

public Object getItem(String table) {
String className = "MIOPATH." + checkCase(table);
Object actualItem = null;
try {
actualItem = Class.forName(className).newInstance();
System.out.println(actualItem.getClass().getName());
} catch(Exception ecc) {
System.out.println(ecc.toString());
}
return actualItem;
}


e checkCase

public String checkCase(String name) {
char firstLetter = name.charAt(0);
if(Character.isLowerCase(firstLetter)) {
name = name.substring(1,name.length());
name = Character.toString(firstLetter).toUpperCase() + name;
}
return name;
}


In questo modo quando vado a verificare se mi ha effettivamente modificato i campi voluti, vedo che in realta' sono memorizzati come per default, quindi pare non li abbia toccati..Se pero' istanzio una oggetto della classe sulla quale voglio lavorare, per esempio

ClasseEsempio miaistanza = new ClasseEsempio()

e ai metodi "metodo.invoke" o "campo.set" passo "miaistanza" invece che "item", cosi' funziona perfettamente, e mi modifica i campi che voglio..

Sapete dirmi dove sbaglio?

Vi prego aiutatemi :cry: :cry:

ceccoggi
06-03-2008, 11:40
upppp:mc: