Contents 1. The class java.lang.Object 2. Equality and hash codes
Working With Objects
3. Cloning, converting to String, finalizing 4. Type conversions 5. Autoboxing
Miloslav Sredkov National Academy for Software Development academy.devbg.org
The Object Class • Base class for all classes
Class java.lang.Object
• Defines the minimal requirements for all reference types • Every java programmer should be familiar with them • Only scalar types don’ ’t inherit it don don’t • However their wrapper classes do
Object Members
Object Members
• protected Object clone()
• void notify()
• public boolean equals(Object obj)
• void notifyAll()
• public int hashCode()
• void wait(long timeout)
• public String toString()
• void wait(long timeout, int nanos) nanos)
• protected void finalize()
• void wait()
• public Class getClass()
(c) 2006 National Academy for Software Development - http://academy.devbg.org
1
Equality vs. Identity • Identity: – Operator ==
Equality and Hash Codes
– References point to the same object • Equality: – .equals(Object) method – Means that the objects represent the –Means same abstract object
Equality Example • Example: String a = "fish"; String b = "fish"; String c = b; a.equals(b); // equality - true; b == c; // identity - true a == b; // identity – may be true or false
Identity and Equality Live Demo
• If you want to compare the objects use the .equals() • If you want to check if the references point to the same object use ==
equals() Method
equals() Method
• Should check whether the abstract objects represented by these objects are equal
• Consistent : multiple invocations of x.equals(y) return the same if the objects are not modified
• Cannot be invoked on null objects
• x.equals(null null) ) should return false x.equals( x.equals(null)
• Reflexive: x.equals(x) • Symmetric: ((x.equals(y)==y.equals(x)) x.equals(y)==y.equals(x)) • Transitive: x.equals(y) && y.equals(z) => x.equals(z)
(c) 2006 National Academy for Software Development - http://academy.devbg.org
2
hashCode() Method • Should return number based on the properties of the abstract object represented by this object • Two equal objects should have the same hash code • a.equals(b) ? a.hashCode() == b.hashCode() • a.hashCode() == b.hashCode() ? a.equals(b) • collision: (!a.equals(b))&&a.hashCode a.equals(b))&&a.hashCode()==b.hashC ()==b.hashC (! (!a.equals(b))&&a.hashCode()==b.hashC ode() • Collisions decrease performance
Default Implementations • equals() – most discriminating possible equivalence relation on objects – x.equals(y) if x == y
• hashCode() – returns int value based on the address of the object when overriding, override both!
Overriding Equals and Hash Code – Example public class Point { private int x; private int y; public boolean equals(Object obj) { // correct behavior on null if(obj instanceof Point) { Point o = (Point)obj; return x == o.x && y == o.y; } return false; } public int hashCode(){ return x * 20143 ^ y * 10169; } }
Overriding Equals and Hash Code Live Demo
• Note that the following is not correct: public boolean equals Point o){ return x == o.x && y == o.y; }
clone() Method • Should return a new object copy of the current • Very useful when the exact type is not known
Cloning Objects Cloneable interface and the clone() method
• Useless for immutable objects • Usually: – x.clone()!=x – x.clone().getClass()==x.getClass() – x.clone().equals(x) • Interface Cloneable must be implemented • Default implementation– –shallow copy implementation implementation–shallow
(c) 2006 National Academy for Software Development - http://academy.devbg.org
3
clone() Example • Example:
clone() Example • Cloning manually:
public class Point implements Cloneable{ private int x; private int y; public Point(int x, int y){ this.x=x; this.y=y; } ... }
public Point clone(){ return new Point(x,y); }
• It is also correct to change return type: public Point clone(){ return new Point(x,y); }
clone() Example • Or with Object.clone() : public Object clone(){ try { return super.clone(); } catch (CloneNotSupportedExceptione){ // Should never reach here because // we implement Cloneable e.printStrackTrace(); return null; } }
toString() Method • String representation of the object • May not contain the whole state information • Should be a concise but informative • Recommended that all classes override this method • Default implementation:
Additional Methods toString() toString() finalize()
toString() Example • With concatenation: public String toString(){ toString(){ return "Point("+x+","+y +")"; "Point("+x+","+y+")"; }
• With format(): format(): public String toString(){ return String.format( "Student(fn=%d, name=%s)", fn, name); }
return getClass().getName() getClass().getName() + '@' + Integer.toHexString(hashCode());
(c) 2006 National Academy for Software Development - http://academy.devbg.org
4
finalize() Method • Something like destructor in other languages • Java does not support destructors!
finalize() Example • Example: class ResourceHolder{
• Called before the object is garbage collected
private ImportantResource resource; ... public void close(){ if(resource.isOpen()){ resource.close(); } }
• No guarantee as to when this will happen! • May not happen before the program exits! • May be used to free resources (open files, connections) • Should be combined with other method, such as close() or dispose()
clone() and toString() Live Demo
public void finalize(){ close(); } }
Comparing Objects Comparable and Comparator interfaces
Comparable Interface – Example
Comparable Interface • This interface imposes a total ordering on the objects of each class that implements it • Lists (and arrays) of objects that implement this interface can be sorted automatically by Collections.sort (and Arrays.sort)
(c) 2006 National Academy for Software Development - http://academy.devbg.org
• Example: public class Student implements Comparable{ private String firstName; private String lastName; private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; }
5
Comparable Interface – Example
Comparable Interface – Example
public String getLastName() { return lastName; }
public String getLastName() { return lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
public int compareTo(Object student) { If(!(student instanceof Student)){ throw new ClassCastException("A Student object expected."); } int studentAge = ((Student) student).getAge(); return this.agethis.age-studentAge; }
public int compareTo(Object student) { if(!(student instanceof Student)){ throw new ClassCastException("A Student object expected."); } int studentAge = ((Student)student).getAge(); return this.agethis.age-studentAge; } }
}
Comparator Interface – Example
Comparator Interface • O bjects are sometimes comparable in Objects many ways • In cases like this, create a Comparator that defines how to compare two objects • To make objects comparable in two ways, then you need two comparators
public class LastNameComparator implements Comparator { public int compare(Object student1, Object student2) { String lastName1 = ((Student) student1).getLastName().toUpperCase(); String firstName1 = ((Student) student1).getFirstName().toUpperCase(); String lastName2 = ((Student) student2).getLastName().toUpperCase(); String firstName2 = ((Student) student2).getFirstName().toUpperCase(); if (!(lastName1.equals(lastName2))){ (!(lastName1.equals(lastName2))){ return lastName1.compareTo(lastName2); }else{ else{ return firstName1.compareTo(firstName2); } } }
Comparable and Comparator
Type conversions
Live Demo
(c) 2006 National Academy for Software Development - http://academy.devbg.org
6
Type Casting • The (Type) operator • Cannot be redefined • May be used between primitive types • May be used to cast between subclass and superclass • Other usages are not allowed!
Primitive Types • Automatic conversion is performed in the following order: byte --> > short --> > int --> > long --> > float --> > double • Note that accuracy may be lost when converting to floating point types • char may be converted automatically to int, long, long, float, float, and double • The result of arithmetic operations with byte and short is int! int! • In all other cases explicit conversion is needed
Primitive Types Example
Primitive Types Example
int i = 5;
//s=b+b;error
// float f = 5.5; error float f = 5.5f;
s = (short) (b + b); //ok
//i = f; error i = (int) f; // ok, i = 5 f = i; //ok, f=5 byte b = 5; short s = 10;
double d = f; //ok d = b; //ok char c = ’A’; s i i
//b = b + b; error //b=(byte) b + b; still error
= = =
c; //error c; //ok,i=65 c * c * c; //oki=274625
long l = i * i; //bad,l=//bad,l=-1890520703 long l2=(long) i * i; //l2=75418890625
b = (byte) (b + b); //ok float f2=l2; //f2=75418894336 //s=b+b;error
To Superclass/Interface • Automatic conversion is performed when object has to be used as some of its supertypes
Primitive Types Live Demo
• You can assign every object to Object variable • You can pass everything as Object argument • Explicit casting is still allowed and may be used to improve readability or to invoke another overload of a method.
(c) 2006 National Academy for Software Development - http://academy.devbg.org
7
To Superclass/Interface
Casting to Subtype
public class Point extends Object implements Cloneable,Comparable{ ... }
• Casting to subtype must be done explicitly
public class Test {
• Has to be done when overriding some Object methods
public static void main(String[] main(String[] args) args) { Point p= new Point(3, 2); Object o = p; Cloneable c = p; ArrayList list = new ArrayList(); list.add(o); // no casting list.add(p); // PointtoObject list.add(c); // CloneabletoObject }
• It is dangerous but sometimes necessary
• If the object is not from the given subtype exception is thrown • If you perform too much conversions to subtype you should review the design • Generics reduce the number of necessary subtype conversions
}
Casting to Subtype • It is also necessary when using not generic collections: Point p= new Point(2, 5); ArrayList list = new ArrayList(); list.add(p); // Point q = list.get(0); // compile error Point q = (Point)list.get(0); Cloneable c = (Cloneable)list.get(0); String s = (String)list.get(0); //exception
Wrapper Classes • For each scalar type there is a wrapper class • Wrapper classes are immutable • They provide lots of methods for manipulation of the corresponding scalar type • They provide useful constants such as Integer.MIN_VALUE MIN_VALUE,Integer. ,Integer.MAX_VALUE MAX_VALUE Integer. Integer.MIN_VALUE,Integer.MAX_VALUE • They support interning with the valueOf() method
(c) 2006 National Academy for Software Development - http://academy.devbg.org
Scalars vs. Objects Boxing, Autoboxing, Unboxing
The Old Way of Boxing • Primitive types (int int,, short, ((int, short, long...) long...) are not objects • They are not acceptable as Object parameters • To put int in collection you had to box it: list.add(new list.add(new Integer(i)) • To get int from a collection you had to unbox it: int x = ( Integer)c.get(key).intValue(); Integer)c.get(key).intValue(); (Integer)c.get(key).intValue();
8
Autoboxing • Autoboxing is added in Java 5 • You can pass a primitive type as argument instead of its wrapper class or Object • You can assign primitive type to a variable of its wrapper class • Boxing is done behind the scene • Boxing decreases performance! (this is valid for both auto and manual boxing!)
Boxing Map Scalar byte short int long float double boolean char
Class Byte Short Integer Long Float Double Boolean Character
Autoboxing Example • List adapter for int array: public static List asList( final int[] a){ return new AbstractList(){ public Integer get(int i){ return a[i]; } // Not working if val == null public Integer set( int i, Integer val){ Integer oldVal = a[i]; a[i] = val; return oldVal; } public int size(){ return a.length; } }; }}
(c) 2006 National Academy for Software Development - http://academy.devbg.org
Unboxing • You can pass an object of the wrapper class as argument instead of its corresponding primitive type • You can assign an object of the wrapper class primitive type to a variable of its wrapper class • You can perform arithmetic operations with objects of the wrapper classes • Unboxing is done transparently
Autoboxing Example • Counting the word frequency: public static void main(String[]args){ Map<String,Integer> m = new TreeMap<String,Integer>(); for (String word : args){ Integer freq = m.get(word); m.put(word, freq== null ? 1 : freq + 1); } System.out.println(m); }
Recommendations • Override the appropriate Object methods depending on how your class will be used • Follow the recommendations strictly! • Think that the user of your objects may not know their type • If these methods are not enough implement additional like equalsIgnoreCase(), equalsIgnoreCase(), md5HashCode(), deepToString() deepToString()
9
Working With Objects
Problems 1. Comment the following equals and hashCode implementations:
Questions?
hashCode()
equals()
return 5; return 0; default
default return this ==obj; return this ==obj;
return 0; return 0; return x;
return true; true; return false; false; return x == obj.x;
return x; return x == obj.x && y == obj.y; return x ^ y; return x == obj.x && y == obj.y;
Problems 2. When is the clone() method usable? 3. If you implement a collection class, how will you implement toString() 4. Will it be necessary for a collection class to override the finalize() method? 5. If you have classes CartesianPoint and PolarPoint which both inherit Point, Point, how will you make conversions between them?
Problems 6. Create a class which overrides the finalize() method to print a message to the standard output. Allocate some object and experiment with System.gc(). System.gc(). Try to finalize the objects without it. 7. Create a class representing a Customer (names and address only) and override all Object methods except the synchronization ones. 8. Try to store and access some of the objects in HashMap. HashMap. 9. Try to make your objects usable in TreeMap
(c) 2006 National Academy for Software Development - http://academy.devbg.org
10