my dog learned polymorphism*
The moose likes Java in General and the fly likes why clone() ? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "why clone() ?" Watch "why clone() ?" New topic
Author

why clone() ?

Pavel Kubal
Ranch Hand

Joined: Mar 13, 2004
Posts: 356
Can you show me the real example of usage of the clone() method? Or whats the reason for this method?

Thanks in advance for your replies
Jeff Albertson
Ranch Hand

Joined: Sep 16, 2005
Posts: 1780
You can use it to copy arrays:

If array had been an instance of String[], for example, so will copy.


There is no emoticon for what I am feeling!
Pavel Kubal
Ranch Hand

Joined: Mar 13, 2004
Posts: 356
Well tank's....I almost forgot that I can override protected method with public one. Now it makes sense
Tony Morris
Ranch Hand

Joined: Sep 24, 2003
Posts: 1608
Originally posted by Pavel Kubal:
Now it makes sense


For a moment, consider the question - What exactly makes sense about copying array elements here and there? Let's look at an array.

An array is a construct that exposes a contract containing three operations. These operations are symbiotic - they cannot be separated. You can define these operations as:
1. E get(int) signals NoSuchIndex
2. void set(E, int) signals NoSuchIndex
3. int getLength
You can formally express the requirement of each operation, but paraphrasing is easier in communication.

The getLength operation is monadic - it forever returns the same value.
The set operation exists to have an observbable side effect on the get operation. In other words, there is a unidirectional relationship from the set operation and the get operation - the set operation has no legitimate existence without the get operation. The get operation may exist in isolation - it is not monadic. The get or set operation may signal to the client the inability to perform the requested operation - the signal name is NoSuchIndex. This signal isused in the event that the client exceeds the permitted bounds (which can be found through the getLength) operation.

There is nothing (not quite true - see below) more to an array contract. How do you produce a different contract implementation with its own identity? Simply, how do you copy an array? You *must* copy elements since arrays are bound by a certain model of representation - this is an abstraction leak that is intrinsic to arrays. In fact, if arrays were nothing more than the above contract, you could implement a "unique contract implementation identity copy" without ever copying elements. Performance bigotry aside, the biggest benefit is that you have met your requirements with greater accuracy by eliminating excess - clients never know, or care, about how you have met their requirement (remember, this was not to copy an array, but to obtain a unique contract implementation identity representing the same "state" of some other contract).

This is exactly the premise that is used for net.tmorris.adt.sequence.Sequence[1] and since the type is immutable (all operations monadic), there is never a legitimate use case for acknowledging contract implementation identity. You can perform, for example, an "append" using net.tmorris.adt.sequence.AppendSequence[2] to be provided with a Sequence contract implementation that appears to have had elements appended.

The question arises, if Sequence is immutable, and I get a Sequence that has a greater length with additional elements, how can an element copy *not* occur? The problem here is that the premise of the question is contrived. Specifically, this part "I get a Sequence that has a greater length with additional elements". This did not occur at all since this is an invalid requirement. I merely obtain a contract implementation identity that met some formal requirement. That I have applied additional context by referring to "additional elements" or whatever it might be, is purely for my own convenience in conceptualisation of the software at hand and unrelated. It is important that it be understood the limitations of such a conceptualisation.

That ends my rant. Bye
[ March 09, 2006: Message edited by: Tony Morris ]

Tony Morris
Java Q&A (FAQ, Trivia)
Tony Morris
Ranch Hand

Joined: Sep 24, 2003
Posts: 1608
[1] http://contractualj.com/api/net/tmorris/adt/sequence/Sequence.html
[2] http://contractualj.com/api/net/tmorris/adt/sequence/AppendSequence.html
Srivatsan santhanam
Greenhorn

Joined: Jan 04, 2006
Posts: 23
Wow.. Tony your reply was just too good.

To add to your reply...

Be careful with usage of Clone as it does only a Shalow Copy.!!


Java Objects passed by Reference ?? -> you are a failure !!
Jeff Albertson
Ranch Hand

Joined: Sep 16, 2005
Posts: 1780
Another thing one could mention about the clone methods for array types (which has nothing to do with clone per se) is that in 1.5 they make use of covariant return types. This means that the signature for String[]'s clone, for example, is:

String[] clone()

So:
Mahadevan Gorti SS
Greenhorn

Joined: Jan 31, 2006
Posts: 18
Apart from normal use of clone as specified Sun and Others, one can use clone innovatively for creating classes in runtime without reflection,etc.

This can be really useful for a case of Classes(various strategies) -- which are derived from a common base class, to be executed for different conditions(strategies)

As sun's clone is too-many if's-but's(for good cause/safety), I have implemented my-own close with an hierarchy of classes which do use creative use of clone. I named my method to create(instead of clone and to stop its unwanted checks/restrictions in my code). I not here saying clone can't be used in my case -- what I am suggesting is another way using clone in practical applications.


So concept is like this:
  • Have a parent class have an abstract methods in Base-class with create method and some doJob/run,preJob/postJob methods for doing real work
  • Let is child class implement the create method which will do a new of that child class . Also child class implements some get/set methods and doJob/run for doinf real-work.
  • When JVM has started , register of all child classes in static Map with public methods to get an instance of that class(with a key of string/integer/some-key) . This could be also from a property file with class-names versus some string/integer/some-key
  • In a class where we need to create different child class for different strategy, get the instance of child-class by passing appropriate key.
  • Now create appropriate child class by calling create method. Do any pre processing in that child class instance by using preJob. Then call doJob/doJob/run. After the that call postJob.




  • By use in this way one can add more strategies or handlers(without using Reflection/switch case statements).


    Same methodolgy can applied on other languages -- C,C++,etc
    Ernest Friedman-Hill
    author and iconoclast
    Marshal

    Joined: Jul 08, 2003
    Posts: 24183
        
      34

    You're describing a sort of degenerate "Abstract Factory" pattern; usually the factory class (the one with the "create" method) is a separate class from the product class (the one that is created.) See here for more of a description.


    [Jess in Action][AskingGoodQuestions]
    Mahadevan Gorti SS
    Greenhorn

    Joined: Jan 31, 2006
    Posts: 18
    Originally posted by Ernest Friedman-Hill:
    You're describing a sort of degenerate "Abstract Factory" pattern; usually the factory class (the one with the "create" method) is a separate class from the product class (the one that is created.) See here for more of a description.


    As I said earlier, you can use clone if you can.

    Definetely I used "Abstract Factory" pattern, but it is not a degenrate case . Even in ""Abstract Factory" pattern case, how one can generate classes in runtime with these conditions these may depends on restrictions on practical situation that arised in my case)
  • One cannot use Reflection -- for performace reasons
  • One cannot implement Cloneable interface in the class heirarchy( the said base/some-sub classes cannot implement Cloneable interface)
  • Similiar code/pattern should be used in corresponding C/C++ code(that complements java code)
  • Use of switch case in "Abstract Factory" implementation is prohibited -- for obvious reasons of long term maintainance issues
  • Use of if-else-statements in "Abstract Factory" implementation is prohibited -- for obvious reasons of long term maintainance issues



  • So tell me if you have any other method/way/suggestion to do same thing in "Abstract Factory" with above conditions.
    Jim Yingst
    Wanderer
    Sheriff

    Joined: Jan 30, 2000
    Posts: 18671
    Mahadevan - could you please take another look at our display name policy and then edit your display name to include a first and last name? Not an abbreviation and/or name of a company or organization. Thanks.


    "I'm not back." - Bill Harding, Twister
    Ernest Friedman-Hill
    author and iconoclast
    Marshal

    Joined: Jul 08, 2003
    Posts: 24183
        
      34

    Originally posted by Mahadevan GSS:
    Definetely I used "Abstract Factory" pattern, but it is not a degenrate case . So tell me if you have any other method/way/suggestion to do same thing in "Abstract Factory" with above conditions.


    First, it sounds like you had an emotional response to the word "degenerate", as if it were an insult. It's not -- I'm using the word in its mathematical sense of "multiple things collapsed into one."

    In the "Factory Pattern", one "Factory" class could make different "Product" classes bases on some input parameter. Usually the creational method is a static method. Your list of objections above are mostly aimed at ways that the "Factory Pattern" can be implemented, and they are certainly valid objections. These objections are all addressed, actually, by the "Abstract Factory Pattern."

    Despite the similar name, the "Abstract Factory Pattern" is a different pattern altogether. In that pattern, you define a "AbstractFactory" interface, often with many different "create" methods that create a family of "Product" classes. Then different implementations of the AbstractFactory create different implementations of the Product classes. The classic example of Product families are GUI widgets: you might have an AWTFactoryImple, a SwingFactoryImpl, and an SWTFactoryImpl. The createButton() method in AbstractFactory would be implemented to create a java.awt.Button in the AWTFactoryImpl, a JButton in the SwingFactoryImpl, etc. Similarly, the same AbstractFactory could have a createList(), createComboBox(), and other methods.

    So I called your implementation "degenerate" because the AbstractFactory and the Product are the same class, and because there is only one create() method -- not because it was bad or perverted in some way.
    Roger Chung-Wee
    Ranch Hand

    Joined: Sep 29, 2002
    Posts: 1683
    Can you show me the real example of usage of the clone() method? Or whats the reason for this method?

    Suppose you have a method which returns a reference to a mutable object (let us call it A). If you do not want the caller to change A, and cannot make A immutable, then you should defensively copy A and return a reference to the copy of A. Cloning is one way of making that copy of A, with the caveat that the cloning is shallow, not deep.


    SCJP 1.4, SCWCD 1.3, SCBCD 1.3
    Jeff Albertson
    Ranch Hand

    Joined: Sep 16, 2005
    Posts: 1780
    Originally posted by Roger Chung-Wee:

    Cloning is one way of making that copy of A, with the caveat that the cloning is shallow, not deep.


    I'm not sure "cloning => shallow". The javadoc for Object.clone states (my emphasis):

    By convention, the object returned by this method should be independent of this object (which is being cloned). To achieve this independence, it may be necessary to modify one or more fields of the object returned by super.clone before returning it. Typically, this means copying any mutable objects that comprise the internal "deep structure" of the object being cloned and replacing the references to these objects with references to the copies. If a class contains only primitive fields or references to immutable objects, then it is usually the case that no fields in the object returned by super.clone need to be modified.
    Jim Yingst
    Wanderer
    Sheriff

    Joined: Jan 30, 2000
    Posts: 18671
    I'd say that the default implementation of clone() inherited from Object does give you a shallow clone. If you override it, you can get a deep clone - or something in between.
    Mr. C Lamont Gilbert
    Ranch Hand

    Joined: Oct 05, 2001
    Posts: 1170

    this is precisely why I do not make clone public. clone has an implementation that people expect when they see the method. shallow copy. But the contract says it does not have to be shallow. So when folks see clone rightfully they don't exactly know what to expect in return. and its not helpful if everyone returns something different from a standard method IMHO.

    I always do something like so


    [ March 24, 2006: Message edited by: Mr. C Lamont Gilbert ]
    David Halliday
    Greenhorn

    Joined: May 10, 2006
    Posts: 2
    Java Newbie Here!

    Hi all, read your post with great interest. I am new to Java and am trying to get my head round the uses of the Clone function.

    I was hoping someone might be able to put me on the right track, cause the CBT software i have doesn't really cover this in enough depth for me.

    I have read and understand how to use the Clone Method, but can someone please answer the following....

    In what circumstances would you use cloning?

    Any help appreciated.

    Cheers
    Stan James
    (instanceof Sidekick)
    Ranch Hand

    Joined: Jan 29, 2003
    Posts: 8791
    Clone gives you a copy of an object at a point in time. You might use it if you want a copy you can modify without affecting the original, or one that will remain unchanged even if another thread modifies the original.

    We also recently discussed with the Prototype pattern.


    A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
    David Halliday
    Greenhorn

    Joined: May 10, 2006
    Posts: 2
    Legend!

    Thanks, thought it might be the case that it ensured the original copy was not being altered. I can imagine this being useful in arrays particularly.

    Many thanks again.

    David
     
    It is sorta covered in the JavaRanch Style Guide.
     
    subject: why clone() ?