Deeper Equals Method

xiaoxiao2021-03-06  73

Deeper Equals Method

The importance of the equals method is not much, as long as the two objects you want to compare, you should implement the equals method, allowing objects to compare the subjects you think.

The following content is just the specification of the API, there is no very deep meaning, but the reason why I will lead it here because these regulations do not really guarantee the implementation in the fact.

1. For any reference type, O.Equals (o) == True is established. 2. If O.Equals (O1) == True is established, then o1.Equals (o) == True must also be set up. 3. O. Equals (O1) == TRUE is established and O.Equals (O2) == TRUE is established, then O1.Equals (O2) == True is also true. 4. If the first call O.Equals (O1) == True is established to establish O and O1 without changing, any call will be established .5.Equals (null) == TRUE is not established at any time.

The above rules are not the most complete expression. For details, please refer to the API documentation.

For Object classes, it provides the most strict implementation, that is, the equals method returns True, which is the reference comparison rather than the value. This implementation is close to what is nothing practical. Significance, so in specific subclasses (relative to Object), if we want to perform the value of objects, you must implement your own equals method.

Let's take a look at the following procedures:

Public Boolean Equals (Object Obj) {IF (Obj == Null) Return False; if (! (! (!) Return False; FieldPosition Other = (FieldPosition) Obj; if (attribute == null) {if (Other. ! attribute = null) {return false;}} else if) {return false (attribute.equals (other.attribute!);} return (beginIndex == other.beginIndex && endIndex == other.endIndex && field == other. Field);

This is the standard implementation of JAVA.TEXT.FIELDPosition in JDK, and there seems to be nothing to say.

Most of my letter or most of the programmers believe that this is the correct legal equals implementation. After all, it is a JDK API implementation.

Still let us talk in fact:

Package debug;

Import java.text. *;

Public class test {public static void main (string [] args) {FieldPosition fp = new fieldPosition (10); fieldPosition fp1 = new mytest (10); system.out.println (fp.equals (fp1)); system.out .println (fp1.equals (fp));}}} class mytest extends fieldPosition {int x = 10; public mytest (int x) {super (x); this.x = x;} public boolean equals (Object O) { IF (o == null) Return False; if (! (o instanceof mytest)) Return false; return ((mytest) o) .x == this.x;}} When running, see what will print:

System.out.println (fp.equals (fp1)); Print TrueSystem.Out.println (fp1.equals (fp)); Print Flase

Two objects, there is an asymmetrical equals algorithm. Where is the problem (brain rushes: Of course, in the JDK implementation BUG)?

I believe that there are too many programmers (except for programmers who don't know how to implement the equals method), they have used instanceof operators when implementing the Equals method, and seeking truth from facts for a long time. Over. Too many tutorials, the documentation gives us a misleading. Some of the slightly available programmers may know that such optimization may be somewhat incomplete but find the key to find a problem. Another extreme is to know that the ashes expert in this technical defect is proposed should not be applied.

We know, "usually" to compare two objects, then they "should" are the same type. So first use the instanceof operator for short circuit optimization, if the comparison object is not with the current object, it does not have to return false, but in fact, "subclasses are an instance of the parent class", so if the subclass o instanceof father The class, always returns True, and it is definitely not short-circuit optimization. The following is more likely to have a variety of situations, one is not able to shape a homic class, and the other is the parent class's private member has no subclasses. Inheritance cannot be compared, and there is also the above asymmetry comparison. There may be too many situations.

So, isn't it possible to optimize with the instanceof operator? The answer is negative, there is still a lot of implementation in JDK, if a class is final, know why it is impossible to have a subclass, why don't I use instanceof to optimize?

In order to maintain the reputation of Sun's development team, I don't indicate which class, but a group member is added after using this method to add this note:

IF (this == obj) // Quick Check Return True; if (! (ipj instanceof xxxxclass) // (1) Same object? Return false; maybe it may be some questions, but I don't know how to do it (I don't know why I didn't play Telephone me ...)

So what about the type of Quick Check for non-final classes?

IF (Obj.getClass ()! = xxxclass.class) return false; compares with the Class object of the comparison object and the Class of the current object, it seems no problem, but if the subclass of this class does not re-implement the equals method, So when the subclass is compared, obj.getClass () is certainly not equal to xxxcalss.class, which is the subclass's Equals will be invalid, so if (obj.getclass ()! = This.getClass ()) Return False; Correct comparison.

Note if (Obj.getClass ()! = This.getClass ()) Return False; just to make subclasses work properly, as for subclasses

If you are inherited, if it is correct, it is not the parent class to consider, that is the subclass implementation, in fact, only in the subclass.

Super.Equals can compare the private variables of the parent class, then compare the class-extension class members in the subclasses. Using dynamics in the parent class

Reflecting all members of the access subclass to compare, although the purpose of the subclass can directly use Equals, this violates the design principle.

You think too far for the future.

Another Quick Check is IF (this == Obj) Return True;

Whether or if the equals method must be more than two objects, it must be the same type? I used "usually", which is also the wishes of most programmers, but some special situations, we can make different types of comparisons, this does not violate the specification. But this special situation is very rare, an inappropriate example is that the Integer class can compare with sort, comparing their value, is the same number of values. (In fact, there is nothing in the JDK API, so I said that it is an inappropriate example)

After completing Quick Check, we must truly implement the "equal" you think. For if the object is equal, there is no high requirement, such as the "people" class you implement, you can think that as long as Name is the same, it is equally, other SEX, AGO can not consider. This is not fully implemented, but if it is fully implemented, it is required to require all attributes, so how to implement the equals method?

Class Human {Private String Name; Private Int Ago; Private STRING Sex; .................. public boolean equals (object obj) {Quick Check ..... .. human other = (human) OJB; return this.name.Equals (Other.Name) && this.ago == OHTER.AGO && this.sex.equals (Other.SEX);}}

About the Equals method is: If you want to rewrite (correctly, it should be a clever) Equals method, then you must rewrite HashCode (). To be a specification, otherwise ........ ..... we still look at this example:

Public final class phonenumber {private final int area; private final int extension;

public PhoneNumber (int areaCode, int exchange, int extension) {rangeCheck (areaCode, 999, "area code"); rangeCheck (exchange, 99999999, "exchange"); rangeCheck (extension, 9999, "extension"); this.areaCode = areaCode; this.exchange = exchange; this.extension = extension;} private static void rangeCheck (int arg, int max, String name) {if (arg <0 || arg> max) throw new IllegalArgumentException (name ": " arg);

Public Boolean Equals (Object O) {if (o == this) Return True; if (! (!) Return False; Phonenumber Pn = (Phonenumber) O; return pn.extension == extension && pn.exchange = = Exchange && pn.areAracode == aacode;}}

Note that this class is Final, so this equals has no problem.

Let's test it:

Public static void main (String [] args) {map hm = new hashmap (); phonenumber pn = new phonenumber (123, 38942, 230); hm.put (PN, "I love you"); phonenumber pn1 = new phonenumber (123, 38942, 230); System.out.Println (PN); System.out.Println ("pn.equals (pn1) is" pn.equals (pn1)); System.Out.println (hm.get (PN1)); system.out.println (hm.get (pn));} Since pn.equals (PN1), then I put (PN, "I love you"); after, Get (PN1) What is NULL? The answer is because their hashcode is different, and HashMap is the main key with hashcode.

So specification requirements, if two objects are compared to Equals, if True is returned, then their HashCode requires returns equal value.

Ok, take a break, take a break. . . . . . . . . . . . . . . .

转载请注明原文地址:https://www.9cbs.com/read-94019.html

New Post(0)