Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 clone() Defined in Object Creates an identical copy –Copies pointers to fields (does not copy fields of fields) –Makes a shallow copy if the object’s.

Similar presentations


Presentation on theme: "1 clone() Defined in Object Creates an identical copy –Copies pointers to fields (does not copy fields of fields) –Makes a shallow copy if the object’s."— Presentation transcript:

1 1 clone() Defined in Object Creates an identical copy –Copies pointers to fields (does not copy fields of fields) –Makes a shallow copy if the object’s class doesn’t implement Cloneable, a CloneNotSupportedException is thrown x.clone() != x; –Modification to X no longer affect X.clone( ) x.clone.getClass() == x.getClass(); Usually, x.equals(x.clone()) == true; –However, this is not a requirement

2 2 Why Override clone() ? First, Object’s clone is a protected method –Its visibility can be increased: Sometimes a deeper copy of a field is required public class X implements Cloneable { public Object clone () throws CloneNotSupportedException { return super.clone(); } public class X implements Cloneable { private A a; public Object clone () throws CloneNotSupportedException { X x = (X)super.clone(); if(a != null) x.a = (A)a.clone(); return x; }

3 3 Pitfalls in Overriding clone() Implementing clone() using a constructor public class X implements Cloneable { public Object clone () throws CloneNotSupportedException { return new X(); } public class Y extends X { //use clone from X } Clone returns wrong type! public class Y extends X { public Object clone () throws CloneNotSupportedException { Y y = (Y)super.clone(); … } Exception!

4 4 Pitfalls in clone() - Cont Using Constructors to copy subobjects –if field a refers to an object of a subclass of A, the cloned object will be different from the original public class X implements Cloneable { private A a; public Object clone () throws CloneNotSupportedException { X x = (X)super.clone(); if(a != null) x.a = new A(); return x; }

5 5 equals(), hashCode() Are defined in Object equals() –Used for state equality testing as opposed to operator == used for reference equality –Used for test containment of object in collection –Used for storing an object in hash-based collection hashCode() –Returns an int value representing the object –Used for storing an object in hash-based collections

6 6 hashCode() in insertion public class SimpleHashSet { private List hashCodes = new ArrayList (); private List > lists = new ArrayList >(); public void add(Object o) { List lst = null; for(int i=0; lst==null && i<hashCodes.size(); ++i) if(hashCodes.get(i) == o.hashCode()) lst = lists.get(i); if(lst == null) { hashCodes.add(o.hashCode()); lists.add(lst = new ArrayList ()); } lst.add(o); }

7 7 equals, hashCode in containment test public class SimpleHashSet { … public boolean exists(Object o) { List lst = null; for(int i=0; lst==null && i<hashCodes.size(); ++i) if(hashCodes.get(i) == o.hashCode()) lst = lists.get(i); if(lst == null) return false; for(Object elem : lst) if(elem.equals(o)) return true; return false; }

8 8 Overriding equals() Default implementation of equals() –is based on the == operator –Two objects are equal if and only if they are the same object Sometimes a programmer specific notion of identity is required: Date d1 = new Date(2007, 7, 7); Date d2 = new Date(2007, 7, 7); d1 != d2; d1.equals(d2) == true;

9 9 equals() Contract The equals() method implements an equivalence relation: –It is reflexive a.equals(a) is true –It is symmetric a.equals(b) ⇔ b.equals(a) –It is transitive a.equals(b) and b.equals(c) ⇒ a.equals(c) –It is consistent repeated calls to the method must yield the same result unless the arguments are modified in-between –No object equals null a.equals(null) = false

10 10 equals() Contract The contract is defined in Java documentation: –http://java.sun.com/j2se/1.3/docs/api/java/lang/Object.html#equal s(java.lang.Object)http://java.sun.com/j2se/1.3/docs/api/java/lang/Object.html#equal s(java.lang.Object) The contract is not enforced by the compiler or the runtime system!

11 11 A Naïve Example class Point{ private final int x; private final int y; public boolean equals(Object o){ if (!(o instanceof Point)) return false; return ((Point)o).x == x && ((Point)o).y == y; } Meets all contract’s demands (as long as inheritance is not involved…)

12 12 Extending the Point Class class ColorPoint extends Point{ private final Color color; public boolean equals(Object o){ if (!(o instanceof ColorPoint)) return false; return super.equals(o) && ((ColorPoint)o).color == color; } ColorPoint p1 = new ColorPoint(1, 2, Color.RED); Point p2 = new Point(1, 2); p1.equals(p2); // ??? P2.equals(p1); // ???

13 13 Another try class ColorPoint extends Point{ final Color color; public boolean equals(Object o){ if (!(o instanceof Point)) return false; if (!(o instanceof ColorPoint)) return o.equals(this); return super.equals(o) && ((ColorPoint)o).color == color; } ColorPoint p1 = new ColorPoint(1, 2, RED); Point p2 = new Point(1, 2); ColorPoint p3 = new ColorPoint(1, 2, BLUE); p1.equals(p2); // ??? p2.equals(p3); // ??? p3.equals(p1); // ???

14 14 A Safe Solution class ColorPoint extends Point{ final Color color; public boolean equals(Object o){ if (o.getClass != ColorPoint.class) return false; return super.equals(o) && ((ColorPoint)o).color == color; } Meets all the contract’s requirements May be too strict An object is never equals to an instance of its super class Even if the derived class doesn’t add fields

15 15 Another Solution The idea: two objects must agree on their equality class Point{ … protected boolean eq(Object o) { if(!(o instanceof Point)) return false; return ((Point)o).x == x && ((Point)o).y == y; } public boolean equals(Object o){ return (this.eq(o) && o.eq(this)); } class ColorPoint extends Point{ … public boolean eq (Object o){ if (!(o instanceof ColorPoint)) return false; return super.eq(o) && ((ColorPoint)o).color == color; }

16 16 hashcode() Contract –It is consistent repeated calls to the method must yield the same int unless the arguments are modified in-between –Must generate equal values for equal objects We see that hashcode() is closely related to equals() if you override equals, you must override hashCode

17 17 hashcode / equals contract violation class Point{ final private int x, y; public boolean equals(Object o){ if (!(o instanceof Point)) return false; return ((Point)o).x == x; } public int hashCode() { return 19 * y; { } public static void main(String[] args) { Set s = new HashSet (); Point p1 = new Point(1, 2); s.add(p1); Point p2 = new Point(1, 3); //p1.equals(p2) is true System.out.println(s.contains(p2)); // false }

18 18 Comparable Interface Why? –equals() can compare objects of different classes –equals() is boolean – can’t be used for sorting A problem –we want compareTo to take a parameter of the same type as the receiver –requires a covariant parameter The Solution –Using generics: public interface Comparable { int compareTo(T o); }

19 19 Implementing Comparable public class Person implements Comparable { public String name; public int age; // Order by age then by name public int compareTo(Person p) { int diff = this.age - p.age; if(diff != 0) return diff; // Use compareTo of String return this.name.compareTo(p.name); }

20 20 Using compareTo() public static > void sort(List lst) { int top = lst.size(); for(int i = 0; i < top; ++i) { for(int j = i+1; j < top; ++j) { T a = lst.get(j-1); T b = lst.get(j); if(a.compareTo(b) > 0) { lst.set(j-1,b); lst.set(j, a); }

21 21 Comparator Interface Used for comparing objects of a class that does not implement Comparable public Interface Comparator { public int compare(T o1, T o2); } public class Utils { public static boolean isOrdered(Comparator comp, T... ts) { for(int i = 1; i < ts.length; ++i) if(comp.compare(ts[i], ts[i-1]) < 0) return false; return true; }


Download ppt "1 clone() Defined in Object Creates an identical copy –Copies pointers to fields (does not copy fields of fields) –Makes a shallow copy if the object’s."

Similar presentations


Ads by Google