# Echte Kopie eines Objektes erstellen



## ZAntjeZ (16. Okt 2004)

Hallo,
 ich möchte von einem Objekt meiner Klasse eine echte Kopie erstellen, d.h. sie sollen danach völlig unabhängig von einander weiter bearbeitbar sein.
Momentan kann ich zwar eine Kopie erstellen, aber sobald ich in einer der beiden Objekte (Original+Kopie) etwas verändere, dann passiert die Änderung auch in dem anderen Objekt, was darauf zurückzuführen ist, dass ich nur die Referenz kopiert habe. Ich habe deswegen clone() von der Schnittstelle Cloneable überschrieben, aber irgendwie geht das auch nicht.
Mein Quellcode:


```
protected Object clone()
	{
		try 
		{
			return super.clone();
		}catch (CloneNotSupportedException e)
		{
			return null;
		}
	}
	
	//Kopieren eines Segments einschließlich seiner Unterobjekte
	public void copy(StructObject child)
	{	
		try
		{
		StructObject so= (StructObject) super.clone();
		so.parent=(StructObject) child.clone();
		//Objekt was kopiert werden soll als ClipObjekt speichern
		setClipObject(so);
		}catch (CloneNotSupportedException e){}
	}
```

Was mach ich falsch?

Danke für jeden Tipp!

Tschau Antje


----------



## Beni (16. Okt 2004)

> aber irgendwie geht das auch nicht.


Eine sehr wage Formulierung...


Angenommen du hast ein Object A und ein Object B:

```
public class A{
  public Object clone(){
    return new A();
  }
}
```


```
public class B extends A{
  public Object clone(){
    return super.clone();
  }
}
```

Wenn du nun ein B clonst, wird ein neues A hergestellt, nicht aber ein neues B (es steht niergends "new B"). D.h. du kriegst keine richtige Kopie...

Du musst in der B.clone-Methode explizit ein neues B herstellen:

```
public class B extends A{
  public Object clone(){
    B b = new B();
    b.setDiesesUndJenes( this.getDiesesUndJenes() );
    return b;
  }
}
```


Ich mach meistens ein Copy-Konstruktor, das erleichert das Kopieren:

```
public class A{
  public A(){}
  public A( A original ){
    setBlupp( original.getBlupp() );
  }
  public Object clone(){
    return new A( this );
  }
}
```


```
public class B extends A{
  public B(){}
  public B( B original ){
    super( original );
    setDiesesUndJenes( original.getDiesesUndJenes() );
  }
  public Object clone(){
    return new B( this );
  }
}
```


----------



## Guest (16. Okt 2004)

Ungefähr so kannst Du Deine Objekte aufbauen, dann geht's.
	
	
	
	





```
public class Foo
{
  private Irgendwas irgendwas;
  ...
  public Foo(Foo foo) {  // Copy-Constructor
    setIrgendwas(foo.getIrgendwas()); 
  }

  public final Irgendwas getIrgendwas() {
    // clone() nur wenn "Mutable", alles adere (immutable und/oder primitive Typen) 
    //direkt zurückgeben
    return (Irgendwas)irgendwas.clone(); 
  }

  public final void setIrgendwas(Irgendwas irgendwas) {
    this.irgendwas = irgendwas;
  }

  protected Object copyInstance(Foo foo) {
    return new Foo(this);
  }

  public final Object clone() {
    return copyInstance(this)  // Kopie zurückgeben
  }
}
```


----------



## Guest (16. Okt 2004)

Ehmm da fählt noch Cloneable


```
public class Foo implements Cloneable
...
```


----------



## ZAntjeZ (16. Okt 2004)

Habs probiert, kommt aber ne NullPointer Exception


```
private StructObject structObjectS;
	
	//Copy-Konstruktor
	public StructObject(StructObject so)
	{
		setStructObject(so.getStructObject());
	}
	
	public final StructObject getStructObject()
	{
		return (StructObject) structObject.clone();
	}

	public final void setStructObject(StructObject strObj)
	{
		this.structObject=strObj;
	}
	
	protected Object copyInstance(StructObject strObj)
	{
		return new StructObject(this);
	}
	
	public final Object clone()
	{	//Kopie zurückgeben
		return copyInstance(this);
	}


public void copy(StructObject child)
	{	
		try
		{
		StructObject so= (StructObject) super.clone();
		so=(StructObject) child.clone();
		//Objekt was kopiert werden soll als ClipObjekt speichern
		setClipObject(so.parent);
		}catch (CloneNotSupportedException e){} 
		
	}
```


----------



## Beni (16. Okt 2004)

Es wäre nützlich, wenn du schreiben würdest, wo diese Exception auftritt.


----------



## ZAntjeZ (16. Okt 2004)

Der Nullpointer komme bei

```
public final StructObject getStructObject()
	{
		return (StructObject) structObject.clone(); //hier kommt die Exception
	}
```

Einmal kam auch folgende Meldung:


```
java.lang.Error: Unresolved compilation problem: 
	structObject cannot be resolved
```


----------



## Beni (16. Okt 2004)

Dann wird wohl "structObject" null sein (es gibt hier ja keine anderen Variablen).

 :arrow: Leg dir eine Instanz dieser Klasse StructObject an, new...


----------



## Guest (16. Okt 2004)

```
return (structObject!=null)?(StructObject) structObject.clone():null;
```


----------



## foobar (16. Okt 2004)

Das geht auch einfacher:

```
public static Object deepCopy(Object o)
{
	try
	{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		new ObjectOutputStream(baos).writeObject(o);
		ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
		return new ObjectInputStream(bais).readObject();
	}
	catch (IOException e)
	{
		e.printStacktrace();
	}
	catch (ClassNotFoundException e)
	{
		e.printStacktrace();
	}
}
```
Die Methode deepCopy erstellt eine tiefe Kopie, eines beliebigen Objekts.


----------



## Guest (16. Okt 2004)

Übrigens, alternativ dazu kannst Du das Objekt durch Streams jagen,
dann hast Du auch eine Kopie.
Es setzt aber voraus, dass alle Attribute der Klasse auch Serializable sind.

```
public class Foo implements Cloneable, Serializable {
  ...
  public Object clone() {
    try {
      ByteArrayOutputStream buf = new ByteArrayOutputStream();
      ObjectOutputStream out = new ObjectOutputStream(buf);
      out.writeObject(this);
      out.flush();
      out.close();
      ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buf.toByteArray()));
      return in.readObject();
    }
    catch(Exception e) {
      return null; // evtl. lieber eine RuntimeException werfen, damit der Aufrufer weiß, was abgeht.
    }
  }
}
```


----------



## Beni (16. Okt 2004)

Hm, ich frag mich allerdings ob das "durch den Stream jagen" nicht eine ziemliche Geschwindigkeitseinbusse gibt, immerhin wird da kräftig mit Reflection und etc. gearbeitet.


----------



## Guest (16. Okt 2004)

Du hast Recht, es ist auf jeden Fall langsamer. 
Aber, wenn es nicht darum geht tausende solcher Objekte zu clonen, dürfte 
es egal sein. Wir reden hier von paar Millisekunden.


----------

