Autore Topic: metodo equals su generici con Gson  (Letto 528 volte)

Offline tonno16

  • Utente storico
  • *****
  • Post: 1187
  • Respect: +57
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
metodo equals su generici con Gson
« il: 05 Febbraio 2015, 18:58:51 CET »
0
Salve a tutti. Di seguito riporto un metodo di una mia classe. Tale metodo ha un oggetto i passato come parametro. Mi servo si altri due metodi nascosti nel codice, i quali ritornano l' intera stringa di un file e viceversa scrivono l'intera stringa su un file. Nel mio caso specifico scrivono e leggono stringa formattata in json. Sono sicuro al 100% che tali metodo funzionano. I Log parlano chiaro. Persino aprendo il mio file con un file manager si nota la perfetta scrittura.

Codice (Java): [Seleziona]
public void applyPlugin(I i) {

        Gson gson = new GsonBuilder().create();

        Type collectionType = new TypeToken<List<I>>(){}.getType();
        List<I> list = gson.fromJson(readFromFile(),collectionType);
       
        // Log.i(MainActivity.TAG,String.valueOf(i.getClass()));
        for(I item : list){
            Log.i(MainActivity.TAG,String.valueOf(item.equals(e)));
        }

        writeOnFile(gson.toJson(list, ArrayList.class));
    }

Come vedete ho cercato di rendere la classe adoperabile anche in altre circostanze. la classe è dichiarata coi parametri. Ovvero:
Codice (Java): [Seleziona]
public class JsonFile<I> { ....metodi...}
La creazione List<I> list avviene "bene". Per bene intendo che con un Log posso anche verificare col cosa effettivamente contenga l' item nel ciclo for. Eppure i.equals(item) ritorna sempre false, nonostante ci siano le stesse informazioni contenute.
Ovviamente io nel mio progetto uso la classe MiaClasse, che è rappresentato dal generico I in questo caso.
Ho ipotizzato che per qualche ragione non venisse usata la classe MiaClasse in tale metodo. Ho quindi fatto un log di i.getClass().....ed effettivamente ritorna com.miopackage.MiaClasse -> quindi giusto.

Sarò ignorante, ma gradirei sapere cosa sbaglio :).

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
Re:metodo equals su generici con Gson
« Risposta #1 il: 06 Febbraio 2015, 14:14:07 CET »
0
Il metodo equals é definito a livello di Object, da best practice di Java dovresti sempre fare l'ovverride del metodo equals() e di hashCode().

Vedi LINK oppure LINK

Offline tonno16

  • Utente storico
  • *****
  • Post: 1187
  • Respect: +57
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:metodo equals su generici con Gson
« Risposta #2 il: 06 Febbraio 2015, 15:22:56 CET »
0
E' la prima cosa che ho pensato. Ma mi sono bloccato per un altro motivo. Dato che io non so che campi acrà il mio oggetto generico, come posso ridefinire un equals che effettivamente riesca a dare true o false??

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
Re:metodo equals su generici con Gson
« Risposta #3 il: 06 Febbraio 2015, 15:32:12 CET »
0
Ma scusa, la tua classe "I" avrá pure delle variabili. o?
Poi una domanda, con quell'equals nel ciclo cosa vorresti "eguagliare"? Cos'é la e?
« Ultima modifica: 06 Febbraio 2015, 15:36:46 CET da emaborsa »

Offline tonno16

  • Utente storico
  • *****
  • Post: 1187
  • Respect: +57
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:metodo equals su generici con Gson
« Risposta #4 il: 06 Febbraio 2015, 15:34:33 CET »
0
Non esiste la mia classe I. I è il generico e MiaClasse.class è la classe che uso.
I viene usato in classi in cui in futuro non adopererò istanze di MiaClasse ma userò istanze di AltraMiaClasse.

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
Re:metodo equals su generici con Gson
« Risposta #5 il: 06 Febbraio 2015, 15:40:49 CET »
0
Al momento della compilazione devi avere una classe che implementi la tua interfaccia o che estenda il tuo generico. A quel punto HAI anche la possibilitá di fare l'override del equals. O sbaglio?

Offline tonno16

  • Utente storico
  • *****
  • Post: 1187
  • Respect: +57
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:metodo equals su generici con Gson
« Risposta #6 il: 06 Febbraio 2015, 16:07:34 CET »
0
Per chiarezza. Ho un classe generica che gestisce generici.

Però MiaClasse non estende niente.
Ho solo
Codice (Java): [Seleziona]
public class MiaClasse implements IMiaClasse {...metodi...}
chiaro che qui posso fare fare l' Override di equals(), ma evidentemente sbaglio qualcosa oppure non riesco a fare l'override corretto.
Faccio un esempio. La classe List nativa di java usa  i generici. Creo tre elementi di tipi MiaClasse. Chiamiamoli A,B e C.
Creo una List<MiaClasse> list1 e List<MiaClasse> list2.
In entrambe le liste aggiunto A B e C.
Faccio un ciclo for per confrontare ogni i-esimo di elemento di list1 con il relativo elemento (quindi stessa posizione in lista) di list2.
Ogni ciclo il metodo equals() mi torna true in quanto gli elementi delle liste sono uguali.
Ma in questo scenario non ho fatto l'Override di equals dentro la classe MiaClasse. Quello che mi suggerisci è giustissimo.
Ma allora per quale motivo nello scenario appena descritto il tutto funziona?

Ho reso l'idea?
Italiano sistemato
« Ultima modifica: 06 Febbraio 2015, 16:54:02 CET da tonno16 »

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
Re:metodo equals su generici con Gson
« Risposta #7 il: 06 Febbraio 2015, 16:46:11 CET »
0
Mi spiace, io non scapisco....non so se é per il tuo italiano leggeermente scorretto o altro.

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:metodo equals su generici con Gson
« Risposta #8 il: 06 Febbraio 2015, 17:01:05 CET »
0
Vado a memoria ma credo che il mio ragionamento sia corretto.

Se tu passi una istanza di I ad un metodo e lo confronti con una istanza di I che viene fuori dalla serializzazione/deserializzazione  il risultato è false a prescindere dal fatto che le due istanze contengano le stesse informazioni.
Se tu deserializzi N istanze di I e ne copi 3 in una lista e 5 in un'altra, il confronto da 3 true e 2 false.

Questo dipende dal modo in cui equals è implementato a livello base. equals su object verifica che l'istanza sulla quale stai lavorando sia la stessa. D'altra parte non può fare molto altro visto che la classe I potrebbe avere 10mila parametri a lui ignoti.

Nel primo caso sono due istanze diverse -> riporta false.
Nel secondo caso sono le stesse istanze referenziate in due posizioni diverse -> riporta true.

 :-)

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
Re:metodo equals su generici con Gson
« Risposta #9 il: 06 Febbraio 2015, 17:04:22 CET »
0
OK,
stai dicendo che se fai una lista con elementi (classi) statici il tutto funziona ma hai problemi quando usi una lista di oggetti creati con Gson?

Se é cosí temo sia Gson il problema. In effetti io uso spesso Gson, ma non li passo un collectiontype, ma un Class<MiaClasseFattaApposita>.

Offline tonno16

  • Utente storico
  • *****
  • Post: 1187
  • Respect: +57
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:metodo equals su generici con Gson
« Risposta #10 il: 06 Febbraio 2015, 17:10:07 CET »
0
grazie undead
Citazione
Vado a memoria ma credo che il mio ragionamento sia corretto.

Se tu passi una istanza di I ad un metodo e lo confronti con una istanza di I che viene fuori dalla serializzazione/deserializzazione  il risultato è false a prescindere dal fatto che le due istanze contengano le stesse informazioni.
Se tu deserializzi N istanze di I e ne copi 3 in una lista e 5 in un'altra, il confronto da 3 false e 2 true.

Ho editato il post, quindi credo ti riferisci alla versione prima di questa tutt' ora presente. O mi sbaglio?
La classe che fa uso di generici si chiama UseGeneric. Fra tutte le porcherie che ha, possiede anche una lista.
Nella mia applicazione dichiaro giustamente UseGeneric<MiaClasse> mUseGeneric = new UseGeneric<>();
Tale classe ovviamente ha un metodo che ritorna tutti gli elementi della lista che ha fra i suoi campi. Qui non ho nessun problema. Se quella lista e eguaglio tutti gli item con un istanza appena creata ho che tale lista contiene un item esattamente uguale a quello appena creato. Lo scrivo perchè ovviamente l'ho testato con codice.
E' proprio questa serializzazione e viceversa che mi frega.

Post unito: 06 Febbraio 2015, 17:12:31 CET
Citazione
OK,
stai dicendo che se fai una lista con elementi (classi) statici il tutto funziona ma hai problemi quando usi una lista di oggetti creati con Gson?

Se é cosí temo sia Gson il problema. In effetti io uso spesso Gson, ma non li passo un collectiontype, ma un Class<MiaClasseFattaApposita>.
Le altre volte anche io faccio cosi. Ma sta volta avrei la necessitò di scrivere codice il pià possibile riusabile. Sono disposto a passare anche il tipo nel metodo in questione. Ma non trovo il procedimento corretto
« Ultima modifica: 06 Febbraio 2015, 17:12:31 CET da tonno16, Reason: Merged DoublePost »

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:metodo equals su generici con Gson
« Risposta #11 il: 06 Febbraio 2015, 17:30:32 CET »
0
Confermo quanto detto a prescindere dall'edit (che non avevo visto ma avevo comunque capito dove andavi a parare).

http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#equals(java.lang.Object)

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

Questo ha a che vedere con il modo in cui java fa riferimento agli oggetti. Ci fu una discussione dai toni molto accesi un paio di anni fa su reference/puntatori e le differenze tra java e c/c++.

Te la spiego con termini approssimativi per rendere l'idea poi sicuramente qualcuno mi smentirà sui dettagli memore della famosa discussione  :D

Devi pensare che quando tu fai pippo tmp = new pippo() succede una cosa particolare. tmp non è pippo ma è un RIFERIMENTO a una istanza di pippo creata "chissadove".

quando chiami una funzione:
manipolapippo(tmp);

all'interno di manipolapippo tu non stai creando un altro pippo, stai manipolando un RIFERIMENTO LOCALE alla stessa istanza di pippo.

Quindi quando tu aggiungi pippo alla lista A e alla lista B stai aggiungendo DUE RIFERIMENTI ALLO STESSO IDENTICO OGGETTO. Questo significa che se modifichi pippo nella lista A ti cambia anche pippo nella lista B.
Perché di fatto sono lo stesso oggetto.

il metodo equals riporta true senza che tu faccia nulla perché pippo dentro A non è solamente uguale a pippo dentro B, sono proprio la stessa cosa. Tecnicamente sono due riferimenti alla stessa istanza. Ecco perché equals funziona, perché si accorge che sono la stessa istanza... quindi implicitamente può affermare che sono uguali!

Al contrario se carichi pippo da json stai creando un riferimento ad una nuova istanza X. Quando ti arriva un pippo del tutto identico che hai creato in un altro modo, è un riferimento ad una istanza diversa, chiamiamola Y.

In quel caso equals ti dice che sono diversi perché non sapendo quali sono i membri/parametri di pippo si limita a verificare se i riferimenti puntano alla stessa istanza. Le istanze sono diverse, quindi equals riporta false.

 :-)

Offline tonno16

  • Utente storico
  • *****
  • Post: 1187
  • Respect: +57
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:metodo equals su generici con Gson
« Risposta #12 il: 06 Febbraio 2015, 17:50:19 CET »
0
Il tuo ragionamento lo seguo. Il mio professore disse: "IN JAVA NON CI SONO I PUNTATORI"......e ci fu un applauso di tutta l'aula. Però ovviamente spiego che sono tutti puntatori (parole povere).

Quello che dici ha molto senso.
Però a sto punto se faccio:
- MiaClasse a = new MiaClasse("001);
- MiaClasse b = new MiaClasse("001);
- list1.put(a) e list2.put(b)

Ciclando le liste dovrebbe dare false il metodo a sto punto o no?
Quindi non mi rimane che fare l' Override di equals in MiaClasse?

Grazie

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:metodo equals su generici con Gson
« Risposta #13 il: 06 Febbraio 2015, 17:59:19 CET »
0
L'oggetto del contendere fu grossomodo questo... tra problemi di terminologia e differenze tra riferimenti/puntatori e così via.
Comunque si: personalmente concordo col professore. In parole povere sono tutti puntatori.  :-)

Dal mio punto di vista se fai quello che hai scritto equals deve restituire false perché sono due oggetti distinti.

Offline tonno16

  • Utente storico
  • *****
  • Post: 1187
  • Respect: +57
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:metodo equals su generici con Gson
« Risposta #14 il: 06 Febbraio 2015, 18:49:10 CET »
0
Tanto per aggiungere qualcosa al thread. Non mi ero mai imbattuto in problematiche del genere.
Codice (Java): [Seleziona]
Item i1 = new Item(1,"uno");
Item i2 = new Item(1,"uno");
               
System.out.print(i1.equals(i2));

torna false. E non me lo sarei aspettato. Grazie