Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 16
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2004
    Messaggi
    643

    Fare l'overriding dei metodi toString(), hasCode(), equals()

    Ciao ragazzi,
    allora ho una 20ina di classi per le quali mi è stato detto di implementare l'overriding dei metodi equals(), toString(), hashCode() seguendo le specifiche di Sun\Oracle

    Non è che potreste farmi un esempio su una delle mie classi? tanto per capire bene che devo fare...poi oviamente per le restanti 19 farò da me...

    Questa è una delle mi classi su cui dovrei fare questa operazione (credo siano poche linee di codice):

    codice:
    import java.io.Serializable;
    import java.util.Date;
    
    public class Addresses implements Serializable {
    
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    	
    	private int addressesPk, contactFk;
    	
    	private String addressesText, addressesNumber, city, countryCode2, districtCode, zipCode, latitude, longitude;
    	private boolean isPrimary;
    	private Date creationDate, lastUpdate;
    	private int creatdBy, modifiedBy;
    	
    	public Addresses(int addressesPk, int contactFk){
    		this.addressesPk = addressesPk;
    		this.contactFk = contactFk;
    	}
    
    	// GETTER PK E FK:
    	public int getAddressesPk() {
    		return addressesPk;
    	}
    
    	public int getContactFk() {
    		return contactFk;
    	}
    
    	// GETTER E SETTER:
    	public String getAddressesText() {
    		return addressesText;
    	}
    
    	public void setAddressesText(String addressesText) {
    		this.addressesText = addressesText;
    	}
    
    	public String getAddressesNumber() {
    		return addressesNumber;
    	}
    
    	public void setAddressesNumber(String addressesNumber) {
    		this.addressesNumber = addressesNumber;
    	}
    
    	public String getCity() {
    		return city;
    	}
    
    	public void setCity(String city) {
    		this.city = city;
    	}
    
    	public String getCountryCode2() {
    		return countryCode2;
    	}
    
    	public void setCountryCode2(String countryCode2) {
    		this.countryCode2 = countryCode2;
    	}
    
    	public String getDistrictCode() {
    		return districtCode;
    	}
    
    	public void setDistrictCode(String districtCode) {
    		this.districtCode = districtCode;
    	}
    
    	public String getZipCode() {
    		return zipCode;
    	}
    
    	public void setZipCode(String zipCode) {
    		this.zipCode = zipCode;
    	}
    
    	public String getLatitude() {
    		return latitude;
    	}
    
    	public void setLatitude(String latitude) {
    		this.latitude = latitude;
    	}
    
    	public String getLongitude() {
    		return longitude;
    	}
    
    	public void setLongitude(String longitude) {
    		this.longitude = longitude;
    	}
    
    	public boolean isPrimary() {
    		return isPrimary;
    	}
    
    	public void setPrimary(boolean isPrimary) {
    		this.isPrimary = isPrimary;
    	}
    
    	public Date getCreationDate() {
    		return creationDate;
    	}
    
    	public void setCreationDate(Date creationDate) {
    		this.creationDate = creationDate;
    	}
    
    	public Date getLastUpdate() {
    		return lastUpdate;
    	}
    
    	public void setLastUpdate(Date lastUpdate) {
    		this.lastUpdate = lastUpdate;
    	}
    
    	public int getCreatdBy() {
    		return creatdBy;
    	}
    
    	public void setCreatdBy(int creatdBy) {
    		this.creatdBy = creatdBy;
    	}
    
    	public int getModifiedBy() {
    		return modifiedBy;
    	}
    
    	public void setModifiedBy(int modifiedBy) {
    		this.modifiedBy = modifiedBy;
    	}
    
    }
    Come potrei rimplementare questi 3 metodi secondo le specifiche di Oracle?

    Tnx
    Andrea

  2. #2
    Utente di HTML.it
    Registrato dal
    Dec 2009
    Messaggi
    1,123
    Dando una tua versione di tali metodi, rispettando la forma "originale"

    codice:
    public boolean equals(Object obj)
    public int hashCode()
    public String toString()
    Ovviamente sono tutti membri di Object.

    http://download.oracle.com/javase/6/...ng/Object.html

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

    Re: Fare l'overriding dei metodi toString(), hasCode(), equals()

    Originariamente inviato da D4rkAng3l
    allora ho una 20ina di classi per le quali mi è stato detto di implementare l'overriding dei metodi equals(), toString(), hashCode() seguendo le specifiche di Sun\Oracle

    Questa è una delle mi classi su cui dovrei fare questa operazione (credo siano poche linee di codice)
    No alt. La implementazione di questi tre metodi non è che è "universale" e chiunque può sapere come farlo nelle tue classi.
    Dipende profondamente da come vuoi trattare le proprietà delle tue classi.

    String toString()
    Questo metodo deve restituire una descrizione "testuale" dell'oggetto, alla fin fine un banale String che devi comporre tu. Tipicamente questa descrizione la si usa quando si vuole ad esempio stampare o loggare una informazione sull'oggetto.
    Non c'è uno standard per la descrizione, basta che sia sufficientemente "esplicativa" per quello che serve e non necessariamente deve essere "localizzata" in qualche lingua o particolarmente forbita o "parlante".

    Quali campi inserire nella descrizione lo devi stabilire tu. Per una classe es. Persona potrebbe essere il-nome poi SPAZIO poi il-cognome oppure altro.


    boolean equals(Object)
    Questo metodo deve indicare (con true/false) se l'oggetto su cui è invocato è di "significato" equivalente a quello passato come argomento.
    Il parametro deve essere Object. Se l'argomento passato è null deve essere restituito false (lo dicono le specifiche di equals in Object!).
    Tipicamente si verifica se l'oggetto è dello stesso tipo della classe (con l'operatore instanceof) poi si fa il cast e si comparano una o più proprietà dei due oggetti.

    Quali proprietà comparare e quindi in che modo due oggetti debbano essere visti come "equivalenti", lo devi stabilire tu.


    int hashCode()
    hashCode serve tipicamente nelle mappe basate su hash-table. L'obiettivo del metodo è quello di restituire valori che siano il più possibile "sparpagliati" e con meno probabilità di "collisioni" in base allo stato degli oggetti.
    Nota: l'obiettivo NON è quello di restituire valori "univoci" (anche se per certe classi questo è un caso particolare, come per java.lang.Integer).

    Se si ridefinisce equals, si dovrebbe anche ridefinire hashCode. Esiste un "contratto" ben preciso tra equals e hashCode (vedere specifiche). Non implementare uno dei due oppure implementarli male significa tipicamente "rompere" questo contratto. E questo può portare a spiacevoli conseguenze quando questi oggetti vengono usati ad esempio nelle mappe (basate su hash-table come HashMap) come "chiavi".

    Le implementazioni di equals e hashCode devono rispettare questo "contratto" che ha diverse proprietà ma quella fondamentale è che se due oggetti sono "uguali" (in termini di equals() ), allora devono fornire lo stesso hashCode.

    Generalmente se si usa un IDE (Eclipse, NetBeans, ecc...) c'è un wizard apposito che genera il codice per hashCode che è molto "buono" (la bontà, in questo senso, è appunto la capacità di sparpagliare i valori e con meno probabilità di collisioni).
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  4. #4
    Utente di HTML.it
    Registrato dal
    Jun 2004
    Messaggi
    643

    Re: Re: Fare l'overriding dei metodi toString(), hasCode(), equals()

    Originariamente inviato da andbin
    No alt. La implementazione di questi tre metodi non è che è "universale" e chiunque può sapere come farlo nelle tue classi.
    Dipende profondamente da come vuoi trattare le proprietà delle tue classi.

    String toString()
    Questo metodo deve restituire una descrizione "testuale" dell'oggetto, alla fin fine un banale String che devi comporre tu. Tipicamente questa descrizione la si usa quando si vuole ad esempio stampare o loggare una informazione sull'oggetto.
    Non c'è uno standard per la descrizione, basta che sia sufficientemente "esplicativa" per quello che serve e non necessariamente deve essere "localizzata" in qualche lingua o particolarmente forbita o "parlante".

    Quali campi inserire nella descrizione lo devi stabilire tu. Per una classe es. Persona potrebbe essere il-nome poi SPAZIO poi il-cognome oppure altro.


    boolean equals(Object)
    Questo metodo deve indicare (con true/false) se l'oggetto su cui è invocato è di "significato" equivalente a quello passato come argomento.
    Il parametro deve essere Object. Se l'argomento passato è null deve essere restituito false (lo dicono le specifiche di equals in Object!).
    Tipicamente si verifica se l'oggetto è dello stesso tipo della classe (con l'operatore instanceof) poi si fa il cast e si comparano una o più proprietà dei due oggetti.

    Quali proprietà comparare e quindi in che modo due oggetti debbano essere visti come "equivalenti", lo devi stabilire tu.


    int hashCode()
    hashCode serve tipicamente nelle mappe basate su hash-table. L'obiettivo del metodo è quello di restituire valori che siano il più possibile "sparpagliati" e con meno probabilità di "collisioni" in base allo stato degli oggetti.
    Nota: l'obiettivo NON è quello di restituire valori "univoci" (anche se per certe classi questo è un caso particolare, come per java.lang.Integer).

    Se si ridefinisce equals, si dovrebbe anche ridefinire hashCode. Esiste un "contratto" ben preciso tra equals e hashCode (vedere specifiche). Non implementare uno dei due oppure implementarli male significa tipicamente "rompere" questo contratto. E questo può portare a spiacevoli conseguenze quando questi oggetti vengono usati ad esempio nelle mappe (basate su hash-table come HashMap) come "chiavi".

    Le implementazioni di equals e hashCode devono rispettare questo "contratto" che ha diverse proprietà ma quella fondamentale è che se due oggetti sono "uguali" (in termini di equals() ), allora devono fornire lo stesso hashCode.

    Generalmente se si usa un IDE (Eclipse, NetBeans, ecc...) c'è un wizard apposito che genera il codice per hashCode che è molto "buono" (la bontà, in questo senso, è appunto la capacità di sparpagliare i valori e con meno probabilità di collisioni).
    mmm usando Eclipse mi pare di capire che come per i getter ed i setter questi 3 metodi...

    Per quanto riguarda la classe precedentemente postata (Addresses) ho fatto generare ad Eclipse i seguenti metodi:

    toString(): che genera semplicemente la concatenazione di tutte le proprietà della classe

    codice:
    @Override
    	public String toString() {
    		return "Addresses [addressesPk=" + addressesPk + ", contactFk="
    				+ contactFk + ", addressesText=" + addressesText
    				+ ", addressesNumber=" + addressesNumber + ", city=" + city
    				+ ", countryCode2=" + countryCode2 + ", districtCode="
    				+ districtCode + ", zipCode=" + zipCode + ", latitude="
    				+ latitude + ", longitude=" + longitude + ", isPrimary="
    				+ isPrimary + ", creationDate=" + creationDate
    				+ ", lastUpdate=" + lastUpdate + ", creatdBy=" + creatdBy
    				+ ", modifiedBy=" + modifiedBy + "]";
    	}
    Poi ho trovato il wizard di Eclipse per generare contemporaneamente i metodo equals() ed hashCode().

    Tra l'altro equals() fà ESATTAMENTE quello che dicevi te (e che è logico aspettarsi come ridefinizione del metodo equals() ): se i 2 oggetti sono esattamente lo stesso oggetto (stesso riferimento) ritorna true. Se l'oggetto parametro è null ritorna false. Se i 2 oggetti hanno istanze diverse ritorna false. Altrimenti controlla se le proprietà dell'oggetti ricevente e dell'oggetto parametro sono uguali. Se hanno tutte gli stessi valori torna true, altrimenti torna false...

    FANTASTICO...tutto molto bello...hashCode() invece non sò come faccia a ritornare l'hash...non conosco l'algoritmo usato...

    Volevo chiederti...ma con questo wizard che autogenera i 2 metodi equals() ed hashCode() contemporaneamente...vale il contratto di cui parlavi? Cioè che: Se per il metodo equals() autogenerato i 2 oggetti sono UGUALI allora per il metodo hashCode() autogenerato i due oggetti avranno STESSO HASH?

    Se vale questa cosa credo di essere a cavallo e di aver finito ciò che mi è stato chiesto di fare...

    Per completezza questi sono i 2 metodi equals() ed hashcode() autogenerati dal widzard di Eclipse:

    codice:
    /* (non-Javadoc)
    	 * @see java.lang.Object#hashCode()
    	 */
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result
    				+ ((addressesNumber == null) ? 0 : addressesNumber.hashCode());
    		result = prime * result + addressesPk;
    		result = prime * result
    				+ ((addressesText == null) ? 0 : addressesText.hashCode());
    		result = prime * result + ((city == null) ? 0 : city.hashCode());
    		result = prime * result + contactFk;
    		result = prime * result
    				+ ((countryCode2 == null) ? 0 : countryCode2.hashCode());
    		result = prime * result + creatdBy;
    		result = prime * result
    				+ ((creationDate == null) ? 0 : creationDate.hashCode());
    		result = prime * result
    				+ ((districtCode == null) ? 0 : districtCode.hashCode());
    		result = prime * result + (isPrimary ? 1231 : 1237);
    		result = prime * result
    				+ ((lastUpdate == null) ? 0 : lastUpdate.hashCode());
    		result = prime * result
    				+ ((latitude == null) ? 0 : latitude.hashCode());
    		result = prime * result
    				+ ((longitude == null) ? 0 : longitude.hashCode());
    		result = prime * result + modifiedBy;
    		result = prime * result + ((zipCode == null) ? 0 : zipCode.hashCode());
    		return result;
    	}
    
    	/* (non-Javadoc)
    	 * @see java.lang.Object#equals(java.lang.Object)
    	 */
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (!(obj instanceof Addresses))
    			return false;
    		Addresses other = (Addresses) obj;
    		if (addressesNumber == null) {
    			if (other.addressesNumber != null)
    				return false;
    		} else if (!addressesNumber.equals(other.addressesNumber))
    			return false;
    		if (addressesPk != other.addressesPk)
    			return false;
    		if (addressesText == null) {
    			if (other.addressesText != null)
    				return false;
    		} else if (!addressesText.equals(other.addressesText))
    			return false;
    		if (city == null) {
    			if (other.city != null)
    				return false;
    		} else if (!city.equals(other.city))
    			return false;
    		if (contactFk != other.contactFk)
    			return false;
    		if (countryCode2 == null) {
    			if (other.countryCode2 != null)
    				return false;
    		} else if (!countryCode2.equals(other.countryCode2))
    			return false;
    		if (creatdBy != other.creatdBy)
    			return false;
    		if (creationDate == null) {
    			if (other.creationDate != null)
    				return false;
    		} else if (!creationDate.equals(other.creationDate))
    			return false;
    		if (districtCode == null) {
    			if (other.districtCode != null)
    				return false;
    		} else if (!districtCode.equals(other.districtCode))
    			return false;
    		if (isPrimary != other.isPrimary)
    			return false;
    		if (lastUpdate == null) {
    			if (other.lastUpdate != null)
    				return false;
    		} else if (!lastUpdate.equals(other.lastUpdate))
    			return false;
    		if (latitude == null) {
    			if (other.latitude != null)
    				return false;
    		} else if (!latitude.equals(other.latitude))
    			return false;
    		if (longitude == null) {
    			if (other.longitude != null)
    				return false;
    		} else if (!longitude.equals(other.longitude))
    			return false;
    		if (modifiedBy != other.modifiedBy)
    			return false;
    		if (zipCode == null) {
    			if (other.zipCode != null)
    				return false;
    		} else if (!zipCode.equals(other.zipCode))
    			return false;
    		return true;
    	}
    Grazie mille
    Andrea

  5. #5
    Utente di HTML.it
    Registrato dal
    Feb 2007
    Messaggi
    4,157

    Re: Re: Re: Fare l'overriding dei metodi toString(), hasCode(), equals()

    un unico appunto: se concateni tante stringhe un migliore uso delle risorse richiede StringBuffer o StringBuilder, guarda la javadoc

    codice:
    public String toString(){
       StringBuffer buffer = new StringBuffer();
       buffer.append("Addresses [addressesPk=");
       buffer.append("addressesPk");
    //continua tu per tutti gli altri campi. 
    	
       return buffer.toString(); 
    }
    RTFM Read That F*** Manual!!!

  6. #6
    Utente di HTML.it
    Registrato dal
    Jun 2004
    Messaggi
    643
    ok...ma per quanto riguarda il discorso di equals() e hashCode() autogenerati vale quello che ho ipotizzato prima? (ovvero che Eclipse ti genera 2 metodi che rispettano il contratto) o no?

    Grazie

  7. #7
    Utente di HTML.it
    Registrato dal
    Feb 2007
    Messaggi
    4,157
    si rispettano il contratto (almeno fin'ora usati con collection non mi hanno creato problemi). Ti invito cmq a capire la logica che c'è dietro questi 2 metodi, non sia mai che un errore sull'IDE dia problemi che non riesci a capire
    RTFM Read That F*** Manual!!!

  8. #8
    Utente di HTML.it
    Registrato dal
    Jun 2004
    Messaggi
    643
    Originariamente inviato da valia
    si rispettano il contratto (almeno fin'ora usati con collection non mi hanno creato problemi). Ti invito cmq a capire la logica che c'è dietro questi 2 metodi, non sia mai che un errore sull'IDE dia problemi che non riesci a capire
    La logica dell'equals() mi è molto chiara, provvederò a vedermi per bene la logica dell'hashCode(), per quella dovrò documentarmi in maniera ben più approfondita

    Grazie
    Andrea

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

    Re: Re: Re: Re: Fare l'overriding dei metodi toString(), hasCode(), equals()

    Originariamente inviato da D4rkAng3l
    codice:
    @Override
    	public String toString() {
    		return "Addresses [addressesPk=" + addressesPk + ", contactFk="
    				+ contactFk + ", addressesText=" + addressesText
    				+ ", addressesNumber=" + addressesNumber + ", city=" + city
    				+ ", countryCode2=" + countryCode2 + ", districtCode="
    				+ districtCode + ", zipCode=" + zipCode + ", latitude="
    				+ latitude + ", longitude=" + longitude + ", isPrimary="
    				+ isPrimary + ", creationDate=" + creationDate
    				+ ", lastUpdate=" + lastUpdate + ", creatdBy=" + creatdBy
    				+ ", modifiedBy=" + modifiedBy + "]";
    	}
    Corretto. Anche la forma del testo risultante è simile a quanto fanno molte classi del framework.

    Originariamente inviato da D4rkAng3l
    Tra l'altro equals() fà ESATTAMENTE quello che dicevi te (e che è logico aspettarsi come ridefinizione del metodo equals() ): se i 2 oggetti sono esattamente lo stesso oggetto (stesso riferimento) ritorna true. Se l'oggetto parametro è null ritorna false. Se i 2 oggetti hanno istanze diverse ritorna false. Altrimenti controlla se le proprietà dell'oggetti ricevente e dell'oggetto parametro sono uguali. Se hanno tutte gli stessi valori torna true, altrimenti torna false...
    Più "ottimizzazioni" varie come es.:
    codice:
    if (this == obj)
        return true;
    che in realtà sarebbe superfluo (se sono lo stesso oggetto, avranno proprietà uguali!) ma serve appunto a velocizzare nel caso sia frequente confrontare due reference che fanno riferimento allo stesso oggetto.

    Originariamente inviato da D4rkAng3l
    hashCode() invece non sò come faccia a ritornare l'hash...non conosco l'algoritmo usato...
    Non è che c'è un algoritmo universale. Quello che hai generato è molto "buono", perché dà anche un "peso" ai campi (il peso è quel prime di 31).

    Se avessi 3 campi int a, b, c, allora un equivalente compatto e scritto a mano potrebbe essere:

    return a*961 + b*31 + c;

    Ti sembra più chiaro e facile capire il succo dell'algoritmo?
    Il fatto che il peso sia 31 non è un caso ... è un numero "primo" (ci sono questioni teoriche dietro all'uso di numeri primi).


    Originariamente inviato da D4rkAng3l
    Volevo chiederti...ma con questo wizard che autogenera i 2 metodi equals() ed hashCode() contemporaneamente...vale il contratto di cui parlavi? Cioè che: Se per il metodo equals() autogenerato i 2 oggetti sono UGUALI allora per il metodo hashCode() autogenerato i due oggetti avranno STESSO HASH?
    Direi di sì ... a parte bachi dell'IDE.

    Comunque se ti capita di dover scrivere a mano questi 2 metodi, c'è una regoletta a cui ci si può arrivare dopo aver studiato e ragionato sul "contratto" tra i due:

    la implementazione di equals deve essere "accurata" (nel senso di quali proprietà considerare) almeno quanto la implementazione di hashCode.

    Se hashCode considera 3 campi, in equals devi usare anche quei campi (poi equals ne potrebbe trattare qualcuno di più). Detto in altro modo, hashCode non deve trattare campi che sono stati esclusi dal trattamento in equals.

    Originariamente inviato da D4rkAng3l
    Per completezza questi sono i 2 metodi equals() ed hashcode() autogenerati dal widzard di Eclipse
    Ok ma quando dicevo che i campi da trattare li devi stabilire tu ... un motivo c'è. Bisogna ragionarci sopra su quali campi usare.

    La tua classe rappresenta un "indirizzo". Sei sicuro che abbia senso vedere come uguali due indirizzi che hanno stesso addressesPk, contactFk o un lastUpdate??

    Per me 2 indirizzi sono "uguali" se rappresentano la stessa destinazione ... non se hanno la stessa chiave o se sono stati aggiornati nello stesso preciso momento ...


    Originariamente inviato da valia
    se concateni tante stringhe un migliore uso delle risorse richiede StringBuffer o StringBuilder
    La "concatenazione" delle stringhe con l'operatore + usa sotto sotto già un StringBuffer o (da Java 5) StringBuilder.

    return "blabla=" + campo1 + ", bloblo=" + campo2;

    viene tradotto dal compilatore in:

    return new StringBuffer().append("blabla=").append(campo1).ap pend(", bloblo=").append(campo2).toString();

    (o con StringBuilder da Java 5)
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  10. #10
    Utente di HTML.it
    Registrato dal
    Feb 2007
    Messaggi
    4,157
    guarda in termini di prestazioni mi sono trovata a fare una cosa con java 5:
    query su db, carico tutti i dati (sottoset della tabella, non tutti i campi), questi poi li stampo a video (chiedendo il toString()).
    In caso di resultset consistenti, ho notato delle differenze sostanziali in termini di tempi di esecuzione e memoria occupata tra il toString con tutti quegli append e il toString fatto passando io stessa per stringBuilder.
    Il tutto nasceva da un problema presso un cliente (che aveva memoria ridotta rispetto a quella del pc su cui sviluppavo io), quella query automaticamente andava in blocco e restituiva JavaHeapException.
    Il punto chiave era che riuscivo ad avere il set dei dati, ma non riuscivo a terminare la stampa.
    Il workaround è stato appunto concatenare tutte le stringhe con StringBuilder e non con "+" e da quella volta preferisco fare questo lavoro a monte e non a valle.

    ci sono anche letture interessanti, quello l'ho provato con mano
    guarda qui
    RTFM Read That F*** Manual!!!

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.