14. september 2003 - 18:31Der er
20 kommentarer og 1 løsning
Semantisk forskel på equals ifm. arrays kontra ArrayList - hvorfo
Hvis jeg har to arrays:
String a[] = {"x","y"}; String b[] = {"x","y"};
så giver a.equals(b) false fordi at der er tale om to forskellige objekter.
Hvis jeg har to ArrayLists:
ArrayList a = new ArrayList(); ArrayList b = new ArrayList();
a.add("x"); a.add("y"); b.add("x"); b.add("y");
så giver a.equals(b) true fordi at indholdet i de to lister er identisk.
Hvorfor har man valgt at lave sproget sådan? Er det generelt sådan at det kun er arrays som har en anden semantisk betydning af equals, eller er der flere eksempler på dette?
Er der en tekst fra SUN som forklarer hvornår man skal sammenligne værdier og hvornår man skal sammenligne objekt-identitet, samt hvad det er meningen at equals skal gøre?
Jo flere svar med officielle referencer, jo flere points vil jeg give.
Teknologi, AI og forretning er i centrum på Computerworlds Cloud og AI Festival i København d. 18. og 19. september. Se hele programmet for den store konference om strategisk brug af Cloud og AI på: www.cloud-festival.dk
Indicates whether some other object is "equal to" this one.
The equals method implements an equivalence relation:
* It is reflexive: for any reference value x, x.equals(x) should return true. * It is symmetric: for any reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true. * It is transitive: for any reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true. * It is consistent: for any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the object is modified. * For any non-null reference value x, x.equals(null) should return false.
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any 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).
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
ArrayList er en af de klasser der har implementeret sin egen equals.
equals
public boolean equals(Object o)
Compares the specified object with this list for equality. Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements e1 and e2 are equal if (e1==null ? e2==null : e1.equals(e2)).) In other words, two lists are defined to be equal if they contain the same elements in the same order.
This implementation first checks if the specified object is this list. If so, it returns true; if not, it checks if the specified object is a list. If not, it returns false; if so, it iterates over both lists, comparing corresponding pairs of elements. If any comparison returns false, this method returns false. If either iterator runs out of elements before the other it returns false (as the lists are of unequal length); otherwise it returns true when the iterations complete.
Så er det store spørgsmål vel: hvorfor har de lavet det sådan ?
Jeg kender faktisk ikke nogle gode kilder til det.
Men man kan jo deducere lidt i bedste Sherlock stil: * Java understøtter ikke operator overload * det vil ofte være nødvendigt at sammenligne indhold af objekter logisk konklusion: * man skal have en metode til det sund fornuft siger at: * den metod ebør hedde det samme i alle klasser og så er der vel kun tilbage at vælge navnet.
De ting du skriver har jeg allerede tænkt mig frem til (og læst iøvrigt) - jeg har brug for at vide hvorfor.
På sin vis kan jeg godt se at Object-klassens equals-implementation er den eneste der giver mening. Ellers skulle den slet ikke være der, eller Object-klassen skulle være abstrakt (det kunne den vel sagtens være). Det ville under alle omstændigheder give udviklere et dårligt udgangspunkt for at skrive deres egne klasser, da de i så fald partout ville være nødt til at implementere deres egen equals-metode (som så iøvrigt kunne virke på lige så mange forskellige måder som der er udviklere).
På den anden side ser det ud til at SUN godt kunne have lavet et alternativ hvor equals-metoden lavede en parvis sammenligning af sine attributter for at finde resultatet. En metode som man burde kunne nedarve (i hvert fald i de nyere versioner af Java).
Det er i hvert fald inkonsistent at objekt-identitets-sammenligning på den måde er blandet sammen med værdi-sammenligning. Jeg havde nok fundet det noget mere elegant hvis man havde skelnet mere imellem de to.
Med ArrayList kan man vel altid køre en
(Object(a)).equals(b)
for at finde ud af om a og b repræsenterer den samme instans, men det er bare ikke indlysende med mindre man kender hele baggrunden.
Jeg kan godt forestille mig at en equals-metode som sammenligner attributter vil blive noget langsommere, men endnu vigtigere ville man miste muligheden for at checke om variable indeholder det samme objekt, hvilket nok ville være meget rart at have.
Iøvrigt er jeg rimeligt overbevist om at de tidlige versioner af sproget ikke rigtig havde faciliteter til at lave en attribut-vis sammenligning uden at det ville blive noget bøvl. F. eks. reflection er først kommet til for ganske nylig.
Alt det har jeg tænkt over. Jeg savner konkrete referencer fra SUN, hvor de forklarer hvad de tænkte på, da det blev lavet sådan.
Det virker som at Arnold og Gossling aldrig har udtalt sig om hvorfor. Ihvertfald ikke noget der er på nettet.
Bloch bruger 10 sider i hans "Effective Java" på at beskrive hvordan man bruger equals og hvordan man ikke gør det. Men heller ikke han komemr så meget ind på hvorfor.
Der er to former for sammenligninger, som er interessante:
Object Equality (Er det det samme objekt)
Data Equality (Indeholder to objekter, samme data).
Klasse String laver data equality, mens f.eks. Object laver object equality. Klassen ArrayList laver data equality, mens f.eks. [] laver object equality.
Baggrundene er lidt vage og usikre, men bunder jo typisk i, at du skal genfinde noget igen.
Object Equality er ligesom den generelle. Det objekt, som indeholder nogle specifikke data er netop det objekt, og derfor er den eneste, som den ved den er lig med er sig selv.
(Jeg påstår f.eks. også, at jeg selv er et unikt væsen, selv om andre siger, at jeg er snydt ud af næsten på min far :-)
I et objektorienteret paradigme er hvert enkelt objekt unikt, og har sin egen identitet. Det er et tilfælde, hvis den har lighedspunkter med andre.
Hvis du har klassen person, skal beslutningen om to instanser er ens tages af programmøren, for kan 2 mennesker hedde det samme uden at være den samme? Hvis du f.eks. har fundet Hans Jensen i en liste, retter hans adresse, og skal gemme den igen, skal listen lige have en mulighed for at finde referencen, f.eks. igennem equals.
Identity og equality er meget interessant, når man snakker datastrukturer, hvor f.eks. hashstrukturer vil kræve, at hashcode() og equals() fungerer transitivt.
Men hovedregelen er, at hvis du bruger equals metoden kan du forvente at der af programmøren er udtænkt, hvorvidt identitet er direkte sammenlignelig eller ej, hvilket selvfølgelig står i javadoc for den angivne klasse.
Logical>>> Jeg synes ikke at det ser ud tila t du har læst mit spørgsmål. jeg ledte ikke efter en forklaring på hvordan equals virker i forskellige situationer, men en (*officiel*) begrundelse for hvorfor.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.