Methods Common to All Objects :effective java ch3

Item 7: Obey the general contract when overriding equals
Item 8: Always override hashCode when you override equals
Item 9: Always override toString
Item 10: Override clone judiciously
Item 11: Consider implementing Comparable

———————————————————————————————————————————————————————–
Item 7: Obey the general contract when overriding equals (override equal rules)
Putting it all together, here’s a recipe for a high-quality equals method:
1. Use the == operator to check if the argument is a reference to this object. If so, return true.
2. Use the instanceof operator to check if the argument is of the correct type. If not,
return false. Typically, the correct type is the class in which the method occurs.
Occasionally, it is some interface implemented by this class. Use an interface if
the class implements an interface that refines the equals contract to permit
comparisons across classes that implement the interface. The collection interfaces Set,
List, Map, and Map.Entry have this property.
3. Cast the argument to the correct type. Because this cast was preceded by
an instanceof test, it is guaranteed to succeed.
4. For each “significant” field in the class, check to see if that field of the argument matches the corresponding field of this object. If all these tests succeed, return true; otherwise, return false. If the type in Step 2 is an interface, you must access the argument’s significant fields via interface methods; if the type is a class, you may be able to access the fields directly, depending on their accessibility. For primitive fields whose type is not float or double, use the == operator for comparisons; for object reference fields, invoke the equals method recursively; for float fields, translate to int values using Float.floatToIntBits and compare the int values using the == operator; for double fields, translate to long values using Double.doubleToLongBits and compare the long values using the == operator. (The special treatment of float and double fields is made necessary by the existence of Float.NaN, -0.0f, and the analogous double constants; see the Float.equals documentation for details.) For array fields, apply these guidelines to each element. Some object reference fields may legitimately contain null. To avoid the possibility of a NullPointerException, use the following idiom to compare such fields: (field == null ? o.field == null : field.equals(o.field)) This alternative may be faster if field and o.field are often identical object references: (field == o.field || (field != null && field.equals(o.field)))
5-When you are finished writing your equals method, ask yourself three questions:
Is it symmetric, is it transitive, and is it consistent? (The other two properties
generally take care of themselves.) If not, figure out why these properties fail to hold,
and modify the method accordingly.
6-Always override hashCode when you override equals

Example:

public final class PhoneNumber {
private final short areaCode;
private final short exchange;
private final short extension;
public PhoneNumber(int areaCode, int exchange,int extension) {
rangeCheck(areaCode,999, "area code");
rangeCheck(exchange,999, "exchange");
rangeCheck(extension, 9999, "extension");
this.areaCode = (short) areaCode;
this.exchange = (short) exchange;
this.extension = (short) 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 (!(o instanceof PhoneNumber))
return false;
PhoneNumber pn = (PhoneNumber)o;
return pn.extension == extension &&pn.exchange == exchange &&pn.areaCode == areaCode;
}
// No hashCode method!
}

Suppose you attempt to use this class with a HashMap:
Map m = new HashMap();
m.put(new PhoneNumber(408, 867, 5309), “Jenny”);
At this point, you might expect m.get(new PhoneNumber(408, 867, 5309)) to return
“Jenny”, but it returns null.
so you must add hash code method and call it in equal
Item 8: Always override hashCode when you override equals

“You must override hashCode in every class that overrides equals.else this will prevent your class from
functioning properly in conjunction with all hash-based collections, including HashMap,HashSet, and Hashtable”
Item 9: Always override toString (Whether or not you decide to specify the format, you should clearly document your intentions.)
toString method is widely implemented. It provides a simple, convenient mechanism for debugging classes during development.
It is also widely used for logging, and for passing informative error messages to Exception constructors and assertions.
When used in these informal ways

public final class Truck {
private String fName = "Dodge";
private int fNumDoors = 2;
private Date fYearManufactured = new Date();
private String fColor = "Fuchsia";
private List<String> fOptions = Arrays.asList("Air Conditioning");
 /** 
* Intended only for debugging. 
* <P>Here, the contents of every field are placed into the result, with 
* one field per line. 
*/
 @Override public String toString() { 
 StringBuilder result = new StringBuilder();
 String NEW_LINE = System.getProperty("line.separator");
 result.append(this.getClass().getName() + " Object {" + NEW_LINE); 
 result.append(" Name: " + fName + NEW_LINE); 
 result.append(" Number of doors: " + fNumDoors + NEW_LINE);
 result.append(" Year manufactured: " + fYearManufactured + NEW_LINE );
 result.append(" Color: " + fColor + NEW_LINE); //Note that Collections and Maps also override toString
 result.append(" Options: " + fOptions + NEW_LINE); 
 result.append("}"); 
 return result.toString(); 
}
another way by reflection
/** * Intended only for debugging. * 
* <P>Here, a generic implementation uses reflection to print 
* names and values of all fields <em>declared in this class</em>. Note that 
* superclass fields are left out of this implementation. 
* * <p>The format of the presentation could be standardized by using 
* a MessageFormat object with a standard pattern. 
*/
 @Override public String toString() 
 StringBuilder result = new StringBuilder(); 
 String newLine = System.getProperty("line.separator");
 result.append( this.getClass().getName() ); 
 result.append( " Object {" ); 
 result.append(newLine);
 //determine fields declared in this class only (no fields of superclass) 
 Field[] fields = this.getClass().getDeclaredFields(); //print field names paired with their values 
 for ( Field field : fields ) {
 result.append(" "); 
 try {
 result.append( field.getName() );
 result.append(": "); //requires access to private field: 
 result.append( field.get(this) ); 
 } catch ( IllegalAccessException ex ) {
 System.out.println(ex); 

 result.append(newLine); 

 result.append("}"); 
 return result.toString(); 
}
}

Item 10: Override clone judiciously(avoid clone)

copy constructors and static factory methods provide an alternative to clone, and are much easier to implement

 
public final class Galaxy {
  public Galaxy (double aMass, String aName) {
     fMass = aMass;
     fName = aName;
  }

  /**
  * Copy constructor.
  */
  public Galaxy(Galaxy aGalaxy) {
    this(aGalaxy.getMass(), aGalaxy.getName());
    //no defensive copies are created here, since 
    //there are no mutable object fields (String is immutable)
  }

  /**
  * Alternative style for a copy constructor, using a static newInstance
  * method.
  */
  public static Galaxy newInstance(Galaxy aGalaxy) {
    return new Galaxy(aGalaxy.getMass(), aGalaxy.getName());
  }
....

Item 11: Consider implementing Comparable(Implementing compareTo)
The compareTo method is the sole member of the Comparable interface, and is not a member of Object. However, it is quite similar in nature toequals and hashCode. It provides a means of fully ordering objects.

Compare the various types of fields as follows :

 

  • numeric primitive : use < and >. There is an exception to this rule: float and double primitives should be compared using Float.compare(float, float) and Double.compare(double, double). This avoids problems associated with special border values. (Thanks to Roger Orr in the UK for pointing this out.)
  • boolean primitive :  use tests of the form (x && !y)
  • Object : use compareTo. (Note that possibly-null fields present a problem : while x.equals(null) returns falsex.compareTo(null) will always throw a NullPointerException)
  • type-safe enumeration : use compareTo, like any Object
  • collection or array : Comparable does not seem to be intended for these kinds of fields. For example, ListMap and Set do not implementComparable. As well, some collections have no definite order of iteration, so doing an element-by-element comparison cannot be meaningful in those cases.

 

 

 

 

Advertisements

About lorddisk

WebCenter Content, WebCenter Portal, WebCenter Sites,Weblogic, Identity and Access Management (IAM),SSO,OAM,OIM,OAAM,OUD, OPAM,OID, OVD ,Oracle API Gateway ,OBIEE,OEDQ, Oracle ADF, Oracle SOA,J2EE, CackePHP ,PHP,J2SE,J2EE,Spring,Hibernate,JQuery,CSS,Java Script ,Joomla,Drupal,Worpress
This entry was posted in effective java. Bookmark the permalink.