Visualizzazione dei risultati da 1 a 9 su 9
  1. #1

    class.clone ...errore?!?!

    Ciao a tutti, sono un pò in imbarazzo nel presentarvi questo esempio...ma ho veramente dei problemi a capire cosa sto sbagliando...
    Ho implementato il metodo clone nella mia classe. Subito dopo l'esecuzione del comando nel programma faccio una verifica sull'uguaglianza dei due oggetti ed ottengo sempre oggetti diversi..!?!!?!?
    Qual'é il mio errore?

    Grazie a tutti
    Luca

    Allego il sorgente per chiarezza

    codice:
     
    public class Utenti implements Cloneable
    {	
    	
    	private String utente;
    	private String passwd;
    	private String verifica;
    	private String tipo;
    	private String cognome;
    	private String nome;
    	private Boolean abilitato;
    	private java.sql.Timestamp data_cambio_passwd;
    	private java.sql.Timestamp data_abilitazione;
    	private java.sql.Timestamp data_disabilitazione;
    	private java.sql.Timestamp data_ultimo_login;
    	private java.sql.Timestamp data_inserimento;
    	private String login_inserimento;
    	private java.sql.Timestamp data_variazione;
    	private String login_variazione;
    	
    	public Utenti clone() throws CloneNotSupportedException 
    	{
    		Utenti ut = (Utenti) super.clone();
    		return ut;
    	 }
    
      ....
    codice:
    old_current = current.clone();
    if(old_current.equals(current)==false)
    {
      try 
      {
       Messagebox.show("errore");
       } catch (InterruptedException e) 
       {
    	 e.printStackTrace();
        }
    }

  2. #2
    Utente di HTML.it L'avatar di Alex'87
    Registrato dal
    Aug 2001
    residenza
    Verona
    Messaggi
    5,802
    Hai ridefinito il metodo equals? L'implementazione di default ereditata da Object si limita a confrontare i riferimenti e non l'effettivo contenuto degli oggetti.
    SpringSource Certified Spring Professional | Pivotal Certified Enterprise Integration Specialist
    Di questo libro e degli altri (blog personale di recensioni libri) | ​NO M.P. TECNICI

  3. #3
    Grazie per la risposta.
    Non ho effettivamente ridefinito la .equals.... però se devo verificare campo a campo tanto vale scrivere una funzione copy() che copia campo a campo...insomma una deep copy...
    Intendevi questo?

    Luca

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: class.clone ...errore?!?!

    Originariamente inviato da lramellavotta
    codice:
    	public Utenti clone() throws CloneNotSupportedException 
    	{
    		Utenti ut = (Utenti) super.clone();
    		return ut;
    	 }
    Invocare il clone della superclasse (che nel tuo caso è proprio Object) è corretto. Solo che devi sapere che il clone di Object si limita a copiare pedestremente il valore di ogni singolo campo. Se un campo è primitivo ... hai proprio una copia. Se il campo è un reference ... copia proprio il valore del reference. NON clona l'oggetto referenziato!

    Se hai 2 oggetti Utenti A e B (clonato) i loro campi 'abilitato' faranno riferimento allo stesso identico oggetto Boolean (se non null, chiaramente). Il che potrebbe andarti bene ma nella maggior parte casi non è così.

    Quindi l'approccio dovrebbe essere: si invoca clone() di Object per copiare pari pari i campi e per quei campi che sono di tipo reference (e nota: specialmente se sono oggetti "mutabili") si aggiunge del codice per clonare davvero l'oggetto.

    E nota: ho parlato di oggetti mutabili. Prendiamo String (che è immutabile). Se anche i due oggetti "originale" e "clonato" hanno lo stesso riferimento al medesimo oggetto String .... quale problema ci sarebbe? Nessuno, l'oggetto String non può cambiare stato.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Il problema è che... .equals() mi restituisce false anche se i singoli campi sono identici...

    Che fare?

    Luca

    codice:
    	public Utenti clone() throws CloneNotSupportedException 
    	{
    		Utenti ut = (Utenti) super.clone();
    		ut.setData_abilitazione(this.data_abilitazione);
    		ut.setData_cambio_passwd(this.data_cambio_passwd);
    		ut.setData_disabilitazione(data_disabilitazione);
    		ut.setData_inserimento(this.data_inserimento);
    		ut.setData_ultimo_login(this.data_ultimo_login);
    		ut.setData_variazione(this.data_variazione);
    		return ut;
    	 }

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da lramellavotta
    codice:
    	public Utenti clone() throws CloneNotSupportedException 
    	{
    		Utenti ut = (Utenti) super.clone();
    		ut.setData_abilitazione(this.data_abilitazione);
    		ut.setData_cambio_passwd(this.data_cambio_passwd);
    		ut.setData_disabilitazione(data_disabilitazione);
    		ut.setData_inserimento(this.data_inserimento);
    		ut.setData_ultimo_login(this.data_ultimo_login);
    		ut.setData_variazione(this.data_variazione);
    		return ut;
    	 }
    No, così copi i reference esattamente come farebbe (a livello di risultato finale) il clone() di Object!
    Devi clonare (proprio clone() ) gli oggetti.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Ho seguito il tuo consiglio. Ho scritto il seguente codice

    codice:
    ....
    	@Override public boolean equals(Object obj) 
    	{
    	    if (this == obj) return true;
    	    if (!(obj instanceof Utenti)) return false;
    	    Utenti ut = (Utenti)obj;
    
    	    return UtilityVarie.confrontaOggetti.uguale(this.abilitato, ut.abilitato) 
    	        && UtilityVarie.confrontaOggetti.uguale(this.cognome, ut.cognome)
    	        && UtilityVarie.confrontaOggetti.uguale(this.data_abilitazione, ut.data_abilitazione)
    	        && UtilityVarie.confrontaOggetti.uguale(this.data_cambio_passwd, ut.data_cambio_passwd)
    	        && UtilityVarie.confrontaOggetti.uguale(this.data_disabilitazione, ut.data_disabilitazione)
    	        && UtilityVarie.confrontaOggetti.uguale(this.data_inserimento, ut.data_inserimento)
    	        && UtilityVarie.confrontaOggetti.uguale(this.data_ultimo_login, ut.data_ultimo_login)
    	        && UtilityVarie.confrontaOggetti.uguale(this.data_variazione, ut.data_variazione)
    	        && UtilityVarie.confrontaOggetti.uguale(this.login_inserimento, ut.login_inserimento)
    	        && UtilityVarie.confrontaOggetti.uguale(this.login_variazione, ut.login_variazione)
    	        && UtilityVarie.confrontaOggetti.uguale(this.nome, ut.nome)
    	        && UtilityVarie.confrontaOggetti.uguale(this.passwd, ut.passwd)
    	        && UtilityVarie.confrontaOggetti.uguale(this.tipo, ut.tipo)
    	        && UtilityVarie.confrontaOggetti.uguale(this.utente, ut.utente)
    	        && UtilityVarie.confrontaOggetti.uguale(this.verifica, ut.verifica);
    	}
    e questo

    codice:
    		public static class confrontaOggetti
    		{
    			public static boolean uguale(String a, String b)
    			{
    				return a==b;
    			}
    			
    			public static boolean uguale(Boolean a, Boolean b)
    			{
    				return a=b;
    			}
    			
    			public static boolean uguale(java.sql.Timestamp a, java.sql.Timestamp b)
    			{
    				return a == null ? b == null : a.equals(b);
    			}
    			
    			public static boolean uguale(Object a, Object b)
    			{
    				return a == null ? b == null : a.equals(b);
    			}
    			
    			
    		}
    Il problem è che alcuni campi (Definiti Timestamp) cambiano valore aggiungendoSI i millisecondi senza che questi siano presenti nel DB...



    codice:
            private List<Utenti> thelist;
    	private Utenti  current, old_current;
    
    	public void refreshUi() 
    	{
    		UtentiDAO pdao = (UtentiDAO)SpringUtil.getBean("UtentiDAO");
    		Tabbox tbox = (Tabbox)getFellow("tbox");
    		tbox.setSelectedIndex(0);
    		thelist = pdao.findAll();
    		if (thelist.isEmpty() == false )
    			setCurrent(thelist.iterator().next());   <<<------------ !!!!!! E' qui il problema
    		binder.loadAll();		
    	}
    	public void setCurrent(Utenti cur) 
    	{
    		this.current= cur;
    	
    	}


    Il campo Data_variazione prima del setCurrent è: 08/12/2010 08:47:03.0
    Dopo il set Current (che è il campo nel DB) è: 08/12/2010 08:47:03.557

    E' un problema di casting, oppure di JdbcTemplate, oppure sono un pistola?

    Grazie

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da lramellavotta
    e questo

    codice:
    		public static class confrontaOggetti
    		{
    			public static boolean uguale(String a, String b)
    			{
    				return a==b;
    			}
    			
    			public static boolean uguale(Boolean a, Boolean b)
    			{
    				return a=b;
    			}
    			
    			public static boolean uguale(java.sql.Timestamp a, java.sql.Timestamp b)
    			{
    				return a == null ? b == null : a.equals(b);
    			}
    			
    			public static boolean uguale(Object a, Object b)
    			{
    				return a == null ? b == null : a.equals(b);
    			}
    			
    			
    		}
    Mi "sfugge" un attimino il perché hai dovuto fare una "nested" class che contiene vari metodi "uguale" (di cui i primi due sono sbagliati, con == compari solo i reference e a=b è una assegnazione ...).

    Quando in realtà ti sarebbe bastato fare un metodo (privato nella tua classe Utenti o in una classe esterna es. Utility) che è poi solo il:

    boolean uguale(Object a, Object b)

    perché sarebbe valido concettualmente per qualunque tipo di oggetti (String, Boolean, Timestamp, ecc...).
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  9. #9
    Grazie andbin per la precisazione.

    Il problema è che non capendo più il motivo ho iniziato a deviare verso sempre più "strane" forme di programmazione.

    Il problema però rimane...
    Il campo Data_variazione prima del setCurrent è: 08/12/2010 08:47:03.0
    Dopo il set Current (che è il campo nel DB) è: 08/12/2010 08:47:03.557
    Qualche idea?


    p.s. scusa ma mi hanno chiamato in reperibilità e devo scappare. Ci sentiamo domani.
    Grazie

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.