The compareTo method is the sole method in the java.lang.Comparable interface. It is similar in character to Object's equals method, except that it permits order comparisons in addition to simple equality comparisons. By implementing Comparable, a class indicates that its instances have a natural ordering.
Compares a object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. Throws ClassCastException if the specified object's type prevents it from being compared to this project.
The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y.
The implementor must also ensure that the relation is transitive: (x.compareTo(y)>0 && y.compareTo(z)>0) implies x.compareTo(z)>0.
Finally, the implementor must ensure that x.compareTo(y) == 0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all z.
It is strongly recommended, but not strictly required, that (x.compareTo(y)==0) == (x.equals(y)).
A compareTo method must obey the same restrictions imposed by the equals contract: reflexivity, symmetry, transitivity, and non-nullity. The compareTo method should generally return the same results as the equals method. If this provision is obeyed, the ordering imposed by the compareTo method is said to be consistent with equals. If it's violated, the ordering is said to be inconsistent with equals.
A class whose compareTo method imposes an order that is inconsistent with equals will still work
consider the Float class, whose compareTo method is inconsistent with equals.
If you create a HashSet and add new Float(-0.0f) and new Float(0.0f), the set will
contain two elements because the two Float instances added to the set are unequal when compared using the equals method. If, however, you perform the same procedure using a TreeSet instead of a HashSet, the set will contain only one element because the two Float instances are equal when compared using the compareTo method.
Writing a compareTo method is similar to writing an equals method, but there are a few key differences. You don't need to type check the argument prior to casting. If the argument is not of the appropriate type, the compareTo method should throw a ClassCastException. If the argument is null, the compareTo method should throw a NullPointerException.
The Cloneable interface permit cloning but unfortunately it fails to serve this purpose. Its primary flaw is that it lacks a clone method, and object's clone method is protected.
Actually, Cloneable determines the behavior of Object's protected clone implementation: If a class implements Cloneable, Object's clone method returns a field-by-field copy of the object otherwise it throws CloneNotFoundException. In the case of Cloneable, however, it modifies the behavior of a protected method on a superclass. The Cloneable mechanism is extralinguistic: It creates an object without calling a constructor.
So, Copying an object will typically entail creating a new instance of its class, but it may require copying of internal data structures as well. No constructors called.
Process-1:
If you override the clone method in a nonfianl class, you should return an object obtained by invoking super.clone.
In practise, a class that implements Cloneable is expected to provide a properly functioning public clone method.
public Object clone(){
try{
return super.clone();
}catch(CloneNotSupportException e){}
}
If your object contains fields that refer to mutable objects, using this clone implementation can be disastrous. It will throws ArrayIndexOutOfBoundException.
Process-2:
In effect, the clone method functions as another constructor, you must ensure that it does no harm to the original object and that it properly establishes invarients on the clone. In order for the clone method on Class to work properly, it must copy the internals of the class. The easiest way to do this is by calling clone recursively on the elements array
public Object clone() throws CloneNotSupportedException{
Stack result = (Stack) super.clone();
result.elements = (Object[])elements.clone();
return result;
}
This solution would not work if the composite field were final because the clone method would be prohibited from assigning a new value to the field. The clone architecture is incompatible with normal use of final fields referring to mutable objects. So, In order to make a class cloneable, it may be necessary to remove final modifiers from some fields.
To fix this problem, you'll have to copy the linked list that comprises each object individually. Although this will work when objects aren't too long. If too long this could easily cause a stack overflow.
You are probably better off providing some alternative means of object copying or simply not providing the capability. It doesn't make much sense for immutable classes to support object copying because copies would be virtually indistinguishable from the original.
A fine approach to object copying is to provide a copy constructor.
Providing a good toString implementation makes your class much more pleasant to use.
The toString method is automatically invoked when your object is passed to println, the string concatenation operator(+) and etc.
The benefits of providing a good toString method extend beyond instances of the class to objects containing references to these instances, especially collections.
When practical, the toString method should return all of the interesting information contained in the object.
One important decision you'll have to make when implementing a toString method is whether to specify the format of the return value in the documentation.
Extra:
Example: BigInteger, BigDecimal and most primitive wrapper classes.
The disadvantages of specifying the format of the toString return value is that once you've specified it, you're stuck with it for life.
Whether or not you decide to specify the format, you should clearly document your intentions.
Example:
package com.effectivejava;
/**
*
* @author Shaiful Islam(palash)
*/
public class Item9 {
public static void main(String[] args){
Telephone telephone = new Telephone(02, 881, 6480);
System.out.println(telephone.toString());
}
}
class Telephone{
private int areadCode;
private int exchange;
private int extension;
public Telephone(int areaCode, int exchange, int extension) {
this.areadCode = areaCode;
this.exchange = exchange;
this.extension = extension;
}
private static String[] ZEROS = {"", "0", "00", "000",
"0000", "00000", "000000", "0000000", "00000000", "000000000"};
@Override
public String toString(){
return "(" + toPaddedString(this.areadCode, 3) + ") " +
toPaddedString(exchange, 3) + "-" +
toPaddedString(extension, 4);
}
private static String toPaddedString(int i, int length){
String s = Integer.toString(i);
return ZEROS[length - s.length()] + s;
}
}
Following procedures can follow to override hashCode method in java:-
Store some constant nonzero value, say 17 in an int variable called result.
For each significant field f in your object(each field taken into account by the equals method, that is), do the following:
Compute an int hash code c for the field:
If the field is a boolean, compute (f ? 0 : 1)
If the field is a byte, char, short, or int, compute (int)f
If the field is a long, compute (int)(f^(f>>>32))
If the field is float compute Float.floatToIntBits(f)
If the field is an object reference and this class's equals method compares the field by recursively invoking equals, recursively invoke hashCode on the field. If a more complex comparison is required, compute a "canonical representation" for this field and invoke hashCode on the canonical representation. If the value of the field is null, return 0 (or some other constant, but 0 is traditional)
If the field is an array, treat it as if each element were a separate field. That is, compute a hash code for each significant element by applying these rules recursively, and combine these values.
Combine the hash code c computed in previous step a into result as follows: result = 37*result + c;
return result
When you are done writing the hashCode method, ask yourself whether equal instances have equal hash codes. If not, figure out why and fix the problem
It is acceptable to exclude redundant fields from the hash code computation. If a class is immutable and the cost of computing the hash code is significant, you might consider caching the hash code in the object rather than recalculating it each time it is requested. Do not be tempted to exclude significant parts of an object from the hash code computation to improve performance.
EJ-8/57: Always override hashCode when you override equals
You must override hashCode in every class that overrides equals. Otherwise, It will prevent your prevent your class from functioning properly in conjunction with all-based collections, including HashMap, HashSet and Hashtable.
java.lang.Object specification:
Whenever it(equals override) is invoked on the same object more than once during an execution of an application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons in the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
It is not required that if two objects are unequal according to the equals(object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables
Equals objects must have equal hash codes. Because two distinct instances may be logically equal according to the class's equal method, but to the object class's hashCode method, they're just two objects with nothing much in common. Therefore object's hashCode method returns two seemingly random numbers instead of two equal numbers as required by the contract. That's why it is very important to override hashCode when equals override.
Example:
without overriding hashCode method:
package com.effectivejava;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author palash
*/
public class Item8 {
public static void main(String[] args){
System.out.println("testing item8");
Map m = new HashMap();
m.put(new PhoneNumber(408, 876, 5309), "palash");
System.out.println(m.get(new PhoneNumber(408, 876, 5309)));
}
}
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);
}
@Override
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;
}
}
EJ-7/57: Obey the general contract when overriding equals
When override the equals method, must adhere following contract:
It is reflexive: For any reference value x,x.equals(x) must return true
It is symmetric: For any reference values x and y, x.equals(y) must 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) must 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) must return false
Each instance of the class is inherently unique.
You don't care whether the class provides a "logical equality" test.
A superclass has already overridden equals, and the behavior inherited from the superclass is appropriate for this class.
The class is private or package-private, and you are certain that its equals method will never be invoked
Some High quality equals method :
Use the == operator to check if the argument is a reference to this object
Use the instanceof operator to check if the argument is of the correct type
Cast the argument to the correct type
For each "significant" field in the class, check to see if that field of the argument matches the corresponding field of this object
Always override hashCode when you override equals
Don't write an equals method that relies on unreliable resources
Don't substitute another type for Object in the equals declaration
Extra:
o instanceof MyType. Where instanceof operator to check the type is correct or not. It returns false if its first operand is null.
Finalizers are unpredictable, often dangerous, and generally unnecessary. Their use can cause erratic behavior, poor performance, and portability problems.
In the Java programming language, the garbage collector reclaims the storage associated with an object when it becomes unreachable, requiring no special effort on the part of the programmer. The try-finally block is generally used for this purpose.
There is no guarantee that finalizers will be executed promptly. Nothing time-critical should ever be done by a finalizer.
Explicit termination methods are often used in combination with the try-finally construct to ensure prompt termination. Invoking the explicit termination method inside the finally clause ensures that it will get executed even if an exception is thrown while the object is being used.
Foo foo = new Foo();
try{...}finally{
foo.terminate(); //explicit termination method
}
InputStream, OutputStream and Timer use explicit termination method. Also have finalizers that serve as safety nets in case their termination methods aren't called.
Instead of putting the finalizer on the class requiring finalization, put the finalizer in an anonymous class whose sole purpose is to finalize its enclosing instance. A single instance of the anonymous class, called a finalizer guardian, is created for each instance if the enclosing class.
public class Foo{
private final Object finalizerGuardian = new Object(){
protected void finalize() throws Throwable{
}
};
}
Extra:
Don't use finalizers except as a safety net or to terminate noncritical native resources. If you use finalizer then remember to invoke super.finalize.
If you need to associate a finalizer with a public, nonfinal class, consider using a finalizer guardian to ensure that the finalizer is executed, even if a subclass finalizer fails to invoke super.finalize.
Memory leak in program which can silently manifest itself as reduced performance due to increased garbage collector activity or increased memory footprint. In extreme cases, such memory leaks can cause disk paging and even program failure with an OutOfMemoryError, but such failures are relatively rare.
Memory leak known as uintentional object retentions. Memory leaks in garbage collected languages are insidious. If an object reference is unintentionally retained, not only is that object excluded from garbage collection, but so too are any objects referenced by that object and so on.
An added benefit of nulling out references is that, if they are subsequently dereferenced by mistake, the program will immediately fail with a NullPointerException, rather than quietly doing the wrong thing. It is always to detect programming errors as quickly as possible.
Another common source of memory leaks is caches. Once you put an object reference into a cache, it's easy to forget that it's there and leave it in the cache long after it becomes irrelevant.
Extra: Because memory leaks typically do not manifest themselves as obvious failures, they may remain present in a system for years. They are typically discovered only as a result of careful code inspection or with the aid of a debugging toll known as a heap profiler. In netbeans "Profile" option performs that.