The Artima Developer Community
Sponsored Link

Java Answers Forum
Cloning and Interfaces

10 replies on 1 page. Most recent reply: Nov 5, 2004 10:53 AM by Matt Gerrans

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 10 replies on 1 page
Guillaume Taglang

Posts: 18
Nickname: gouyou
Registered: Jul, 2003

Cloning and Interfaces Posted: Oct 27, 2004 10:53 PM
Reply to this message Reply
Advertisement
Hi all !

I just hit a really stupid problem in Java.

Writing some software and doing things the nice way, I'm using interfaces. Today I needed to clone a list. No problem, remembering my first day with Java I made:

List myList = new LinkedList();
//...
List myClonedList = (List) list.clone();


Oops ! the IDE told me that the clone method was protected ... Memory started it's work ... Oh yeah ! There was a Cloneable interface, back to the code:

List myList = new LinkedList();
//...
List myClonedList = (List) ((Cloneable) list).clone();


Re-Oops ! IDE still complaining: Cloneable doesn't have a clone() method.

So after going back to the javadoc, I'm back to plain old LinkedList. Sure my modern IDE with refactoring and all the nice stuff can handle it. But I'm not sure what I will do the next time I need to clone an object especially when I didn't write it.

I hope someone can explain me a good solution or at least the reasons of having the clone method protected and the interface Cloneable not declaring it ...

Cheers,
Guillaume


Matthias Neumair

Posts: 660
Nickname: neumi
Registered: Sep, 2003

Re: Cloning and Interfaces Posted: Oct 28, 2004 12:08 AM
Reply to this message Reply
You wrote:


List myList = new LinkedList();
//...
List myClonedList = (List) list.clone();



Did you really type it that way?

Try
List myClonedList = (List) myList.clone();
instead

Or does "list" reference to the same object as "myList"?



Does List extend LinkedList? Then try adding the method:

public Object clone () {
return super.clone();
}

Guillaume Taglang

Posts: 18
Nickname: gouyou
Registered: Jul, 2003

Re: Cloning and Interfaces Posted: Oct 28, 2004 3:18 AM
Reply to this message Reply
Oops ! your right should have been:
List myClonedList = (List) myList.clone();


List does not extends LinkedList, LinkedList implements List (they are part of java.util)

A little more code to explain the situation. You start with:
interface MyInterface extends Cloneable {
    void a();
}
 
public class MyFirstImplementation implements MyInterface {
    public void a() {}
    public Object clone() { return super.clone(); }
}
 
public class MySecondImplementation implements MyInterface {
    public void a() {}
    public Object clone() { return super.clone(); }
}


Now in some method you have:
void doSomething(MyInterface o) {
    // o is an instance of either MyFirstImplementation or MySecondImplementation
 
    // Now, I was expecting this:
    MyInterface clone = (MyInterface) o.clone();
    // or this:
    MyInterface clone = (MyInterface) ((Cloneable) o).clone();
    // to work .
}


To fix the problem you should do something like:
interface ReallyCloneable extends Cloneable {
    Object clone();
}
 
interface MyInterface extends ReallyCloneable {
    void a();
}


Which is not working in my case: trying to use the java.util.List interface with java.util.ArrayList and java.util.LinkedList implementation. So even if you know that a standard java class is cloneable, you cannot clone it simply if you are using interfaces (good design): the clone() method in Object is protected and the interface Cloneable doesn't include the method clone().

Cheers,
Guillaume

Matthias Neumair

Posts: 660
Nickname: neumi
Registered: Sep, 2003

Re: Cloning and Interfaces Posted: Oct 28, 2004 11:30 AM
Reply to this message Reply
Now I think I get you. I thought you had created a class extending LinkedList.

The problem:
LinkedList.clone() is protected.
You find the reason for this in the api: The elements don't get cloned, so there is no practical use for the clone()-Method, at least no on I can think of.

super.clone() does no good, too. Because that would be the same as ((java.util.AbstractSequentialList)this).clone()

(List)myLinkedList.clone() should result in a Syntax error (protected access).
((List)myLinkedList).clone() won't work either. In this case I'm not sure if the compiler will find an error, but at Runtime you definitively will get one.



I suppose you want a copy of the LinkedList object with a copy of the elements?

In this case there ist no simple solution.

One way to do it would be to create a sub class of LinkedList and writing your own clone() method.
In this method you create a new LinkedList object (or an instance of the sub class) and copy every element from the original list in the new one. Or you clone the single elements and copy the clones in the new list, if cloning them is possible.

Guillaume Taglang

Posts: 18
Nickname: gouyou
Registered: Jul, 2003

Re: Cloning and Interfaces Posted: Oct 28, 2004 2:25 PM
Reply to this message Reply
Cloning only the list but not the element of the list is perfectly fine in my case (I need to find a couple of path in a graph and need to duplicate the current path if it is a valid solution), it's even really good in a couple of case (e.g. the Flyweight pattern).

I was expecting that something like:
((Cloneable) list).clone()

would work.

The implementation of the clone() method is public in all the implementation of the List interface in the java.util package.
These implementation are all implementing Cloneable.

My point is that if you are using the List interface in your code there is no way to call the clone() method in an elegant way. Casting to Cloneable would be the good solution, instead you have to do something like:
if(list instanceof LinkedList)
    clone = ((LinkedList) list).clone();
else if(list instanceof ArrayList)
    clone = ((ArrayList) list).clone();

or extend the List with some dummy class implementing a ReallyCloneable interface.

I guess it will just be one of the things that I do not and will not understand in Java. I perfectly understand why clone() is a protected method in Object, but I do not see why Cloneable is not including this method, after all if I'm implementing the Cloneable interface, or if I'm ready to make a cast, I should know what are the implication ...

Cheers,
Guillaume

Simon Springall

Posts: 2
Nickname: simon97062
Registered: Oct, 2004

Re: Cloning and Interfaces Posted: Nov 2, 2004 5:28 PM
Reply to this message Reply
Why not simply create a new List from the old, instead of using clone() ?

List myClonedList = new LinkedList(myList);

Matt Gerrans

Posts: 1153
Nickname: matt
Registered: Feb, 2002

Re: Cloning and Interfaces Posted: Nov 3, 2004 12:40 AM
Reply to this message Reply
List myClonedList = new LinkedList(myList); seems to work, but forces the choice of a specific list type again. Presumably List myClonedList = (List)myList.clone(); would create a list of the same type as the original, whether it be LinkedList, ArrayList, Vector or some other.

This is probably not much more satisfying:
   List myClonedList = myList.subList(0,myList.size()-1);

Guillaume Taglang

Posts: 18
Nickname: gouyou
Registered: Jul, 2003

Re: Cloning and Interfaces Posted: Nov 4, 2004 8:39 AM
Reply to this message Reply
Nope, subList() is not really better, the returned list is a range of the original list and uses the original list for all it's operation.

Cheers,
Guillaume

Matt Gerrans

Posts: 1153
Nickname: matt
Registered: Feb, 2002

Re: Cloning and Interfaces Posted: Nov 4, 2004 8:58 AM
Reply to this message Reply
What makes you think that?

Maybe what you are really interested in is a deep copy, so that you get copies of all the objects in the list, as well as a new list? A copy of a list is just a new list of the references. Modifying the copied list won't affect the original list, but modifying mutable objects in either list will affect the other (since they are both referring to the same object).

Guillaume Taglang

Posts: 18
Nickname: gouyou
Registered: Jul, 2003

Re: Cloning and Interfaces Posted: Nov 5, 2004 5:05 AM
Reply to this message Reply
> What makes you think that?

The API, if you are taking a look at the sample usage of subList(), it's clear that they meant it for range operation on a list.

> Maybe what you are really interested in is a deep copy, so
> that you get copies of all the objects in the list, as
> well as a new list? A copy of a list is just a new list
> of the references. Modifying the copied list won't
> affect the original list, but modifying mutable objects in
> either list will affect the other (since they are both
> referring to the same object).

I'm not interested in a deep copy. I'm doing some search in complex graphs and I need to manipulate a bunch of path. The path are lists of nodes which explains why I'm in need of cloning the list but not its content.

Cheers, Guillaume

Matt Gerrans

Posts: 1153
Nickname: matt
Registered: Feb, 2002

Re: Cloning and Interfaces Posted: Nov 5, 2004 10:53 AM
Reply to this message Reply
Hmm... Yes, you are correct. It looks like if you remove() an item in a sublist, the original is unaffected, but if you clear() the sublist, that portion of the original will be cleared.

Perhaps they ought to introduce this to replace Cloneable:
interface Clonable
{
    Object clone();
}

In the next release, killing two birds (the misspelling and the missing method) with one cliche. I guess for a little more backward compatibility it might be:
interface Clonable extends Cloneable
{
    Object clone();
}


I think the intention of the Cloneable interface is to behave only as a tag (like a C# attribute) for reflection to determine whether an object can be cloned. However, you need to implement the method clone() for this purpose, so why not have it in the interface? I think maybe it was explained in Josh Bloch's Effective Java, but I forget the rationale and I don't have the book with me.

So it looks like maybe you are stuck with the clunky instanceof hack. Of course, if you get passed an instance of some new implementation of List that you weren't expecting, you'll be hosed.

Flat View: This topic has 10 replies on 1 page
Topic: help plz. i want a java supported emulator with midp 2.0 Previous Topic   Next Topic Topic: passing array in java by value-result?

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use