0

I can't find a solution about cloning inner classes problem (http://bugs.sun.com/view_bug.do?bug_id=4206170). A cloned inner class has wrong outer instance.

class:

public class Outer implements Cloneable {

    public Inner inner = new Inner();

    @Override
    public Outer clone() {
        try {
            Outer clone = (Outer) super.clone();
            clone.inner = inner.clone();
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new Error( "CloneNotSupported: " + e.getMessage());
        }
    }

    public class Inner implements Cloneable {
        @Override
        public Inner clone() {
            try {
                Inner clone = (Inner) super.clone();
                return clone;
            } catch (CloneNotSupportedException e) {
                throw new Error( "CloneNotSupported: " + e.getMessage());
            }
        }
        public Outer getOuter() {
            return Outer.this;
        }
    }

}

and test:

import org.junit.Test;
import static org.junit.Assert.*;

public class InnerCloneTest {

    @Test
    public void test(){
        Outer outer1 = new Outer();
        Outer outer2 = outer1.clone();
        assertNotSame(outer1, outer2);//OK
        assertNotSame(outer1.inner, outer2.inner);//OK
        assertSame(outer1.inner.getOuter(), outer1);//OK
        assertSame(outer2.inner.getOuter(), outer2);//ERROR
        assertNotSame(outer1.inner.getOuter(), outer2.inner.getOuter());//ERROR
    }

}

Should I use constructor instead of clone?

It seems to be only constructor suitable for it.

    //clone.inner = inner.clone(); //don't work
    //clone.inner = clone.inner.clone(); //don't work
    clone.inner = clone.new Inner(); //OK

And it seems to be use non-static inner classes is an antipattern. They are unserializable. Spring IoC can’t instantiate them.

alexbt
  • 16,415
  • 6
  • 78
  • 87
  • 3
    It makes total sense to me - when you create a clone of an inner class, that keeps a reference to the same instance of the outer class. The fact that you *happen* to be doing this in the context of cloning an outer class as well is irrelevant to the behaviour of `clone()` on the inner class instance. – Jon Skeet Jan 23 '14 at 11:56
  • 1
    Use the workaround from the bug report. – Marko Topolnik Jan 23 '14 at 12:01
  • Forget about `clone()` and use an explicit copy mechanic under your control. http://stackoverflow.com/questions/2427883/clone-vs-copy-constructor-which-is-recommended-in-java – zapl Jan 23 '14 at 12:21

0 Answers0