• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Effective Java - Override clone() method judiciously
 

Effective Java - Override clone() method judiciously

on

  • 6,311 views

 

Statistics

Views

Total Views
6,311
Views on SlideShare
6,308
Embed Views
3

Actions

Likes
2
Downloads
28
Comments
1

1 Embed 3

http://www.linkedin.com 3

Accessibility

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

11 of 1 previous next

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • Thanks for the great and well-explained content!
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Effective Java - Override clone() method judiciouslyEffective Java - Override clone() method judiciously Presentation Transcript

    • Effective Java - Item 10
        • By
        • Ferdous Mahmud Shaon and
        • Hasan Shihab Uddin
        • Software Engineer,
        • Escenic Bangladesh.
    • Item 10: Override clone judiciously
      • Cloneable interface
      • clone() method
      • shallow vs. deep cloning
      • // consider the following class:
      • public class Swimmer {
      • private String name;
      • private float swimTime;
      • private Date eventDate;
      • public Swimmer() …
      • public String getName() { return name; }
      • public float getSwimTime() { return swimTime; }
      • public Date getEventDate() { return eventDate; }
      • }
      assume: default constructor reads data from file Problem: breaks encapsulation!
      • // application programmer writes:
      • Swimmer cu1 = new Swimmer();
      • Date d = cu1.getEventDate();
      • d.setYear(1982);
      • // problem!! Date is mutable
    • Swimmer String name swimTime eventDate 26.31 Kristen Date year 2005 etc. 1982 Immutable mutable cu1 d
    • Aliasing problem
      • both d and cu1.eventDate refer to the same exact object
      • so, if you change one, you change the other
      • solution: accessor should return a “clone” (copy) of the event date
      • is this a problem for the name field?
      • clone() makes a copy of an object … the question is: what kind of copy?
    • protected Object clone () throws CloneNotSupportedException
      • Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object. The general intent is that, for any object x:
      • x.clone() != x
      • will be true, and that the expression:
      • x.clone().getClass() == x.getClass()
      • will be true, but these are not absolute requirements. While it is typically the case that:
      • x.clone().equals(x)
      • will be true, this is not an absolute requirement.
    • Object.clone()
      • makes a field-by-field, bit-by-bit copy of a cloneable object
      • throws CloneNotSupportedException for any class which doesn’t implement cloneable
    • Cloneable interface
      • the Cloneable interface is a “ marker ” interface – it has no methods !
      • the purpose of a marker interface is to allow you to use instanceof in a type inquiry:
      • if (x instanceof Cloneable) // clone allowed
      • repeat: clone() is not in the Cloneable interface; the clone() method is in class Object
    • Example: Class Die ( not implementing Cloneable )
      • Die d1 = new Die();
      • Die d2 = (Die) d1.clone(); // ERROR
      • need to do the following:
      • implement Cloneable interface
      • override Object.clone() method
      note the cast (since clone returns Object)
      • public class Die implements Cloneable
      • {
      • public Object clone() {
      • try
      • {
      • return super.clone();
      • }
      • catch (CloneNotSupportedException e)
      • {
      • throw new InternalError(e.toString());
      • }
      • }
      • // etc.
      calls Object.clone() can’t happen, since Die is Cloneable
    • Cloning swimmer:
      • It’s not enough to use the Object cloning method, since it only makes a “ shallow ” copy
      • public class Swimmer implements Cloneable
      • {
      • public Object clone() {
      • try
      • {
      • return super.clone();
      • }
      • catch (CloneNotSupportedException e)
      • {
      • throw new InternalError(e.toString());
      • }
      • }
      • // etc.
    • Cloning swimmers:
      • Swimmer s1 = new Swimmer();
      • Swimmer s2 = (Swimmer) s1.clone();
      • What’s the problem? - Have used the shallow copy. So the references still point to the same exact objects. Not a problem for immutable objects, but is problematic for mutable objects
      • public class Swimmer implements Cloneable {
      • public Object clone() {
      • try {
      • Swimmer s = (Swimmer) super.clone();
      • s.eventDate = (Date) eventDate.clone();
      • return s;
      • } catch (CloneNotSupportedException e) {
      • throw new InternalError(e.toString());
      • }
      • }
      makes a bit-by-bit copy copies the Date
    • It is up to the class designer to determine whether:
      • the default clone() is good enough:
      • “ Shallow cloning ”
      • the default clone() can be overriden by calling clone on each non-primitive, mutable instance variable:
      • “ Deep cloning ”
      • give up – don’t use cloning
    • Case 1: shallow cloning
      • Default clone is good enough:
      • All instance variables are either primitive values or, and every superclass up to immutable objects Object is well-behaved
      • implements Cloneable interface
      • in the class, define a method:
      • public Object clone() that calls
      • super.clone() and returns that copy
      • public class X implements Cloneable
      • {
      • public Object clone() {
      • try
      • {
      • return super.clone(); // shallow clone
      • }
      • catch (CloneNotSupportedException e)
      • {
      • throw new InternalError(e.toString());
      • }
      • }
    • Case 2: deep cloning
      • The default clone can be patched up:
      • implement Cloneable interface
      • in your class, define a method:
      • public Object clone()
      • that calls super.clone() to make a shallow copy, plus makes deep copies of fields that refer to mutable objects by calling clone() individually on those fields
      • public class X implements Cloneable
      • { private int a; // primitive
      • private String b; // reference to immutable object
      • private Y c; // where class Y has mutator methods
      • private Z d; // where class Z has mutator methods
      • public Object clone() { // deep clone
      • try {
      • X other = ( X ) super.clone(); // fields a & b OK
      • other.c = (Y) c.clone(); // fix c by making a copy
      • other.d = (Z) d.clone(); // fix d by making a copy
      • return other; // return the deep clone
      • } catch (CloneNotSupportedException e) {
      • throw new InternalError(e.toString());
      • }
      • public class Swimmer implements Cloneable {
      • private String name;
      • private float swimTime;
      • private Date eventDate;
      • public Swimmer() …
      • public String getName() { return name; }
      • public float getSwimTime() { return swimTime; }
      • public Object clone() { /* case 2: deep clone */ }
      • public Date getEventDate() {
      • return (Date) eventDate.clone();
      • // note: Date is cloneable
      • }
      • }
      fix the accessor by returning a copy
      • public class A implements Cloneable {
      • public HashMap map;
      • public A() {
      • map = new HashMap();
      • map.put("key1", "value1");
      • map.put("key2", "value2"); }
      • public Object clone() {
      • try {
      • A other = (A)super.clone();
      • other.map = (HashMap)map.clone();
      • return other; } catch (CloneNotSupportedException e) {
      • throw new InternalError(e.toString()); }
      • } }
    • Case 3: don’t use cloning
      • Consider providing a copy constructor or a static factory method …
      • copy constructor – is simply a constructor that takes a single argument whose type is the class containing the constructor, for example, public Yum(Yum yum);
      • A minor variant is to provide a static factory in place of a constructor: public static Yum newInstance(Yum yum);
    • Advantages over cloning…
      • Cloneable/clone: They do not rely on a risk-prone extralinguistic object creation
      • they do not demand unenforceable adherence to ill-documented conventions;
      • they do not conflict with the proper use of final fields; they do not require the client to catch
      • an unnecessary checked exception ; and
      • they provide a statically typed object to the client. So type-casting
      • public StudioGroup(final Group pGroup) {
      • mId = pGroup.getId();
      • setName(pGroup.getName());
      • setDescription(pGroup.getName());
      • Status status = pGroup.getStatus();
      • setStatus(status == null ? null : new StudioStatus(status));
      • List<Category> categories = pGroup.getCategories();
      • setCategories(categories == null ? null :
      • new ArrayList<Category>(categories));
      • setHotTopicsAccessible(pGroup.isHotTopicsAccessible());
      • }
      • public Object clone() throws CloneNotSupportedException {
      • Group group = (Group) super.clone();
      • Status status = group.getStatus();
      • group.setStatus(status == null ? null : (Status) status.clone());
      • List<Category> categories = group.getCategories();
      • group.setCategories(categories == null ? null : (List<Category>) categories.clone());
      • return group;
      • }
      • Given all of the problems associated with Cloneable, it is safe to say that other interfaces should not extend it and that classes designed for inheritance should not implement it.
      • Be aware that if you do not at least provide a well-behaved protected clone method on a class designed for inheritance, it will be impossible for subclasses to implement Cloneable.
    • Thank You