Object mit clone kopieren

Generic1

Top Contributor
Hallo,

mir ist folgender Code nicht gnaz klar, ich kopiere eine Hashtable mit clone() und es wird eine Shallow- Copy gemacht -> das heißt für mich, dass nur die Referenz auf die Hashtable kopiert wird nicht aber deren Inhalt -> aber es wird anscheinend doch das ganze Objekt gekloned, also ein deep copy gemacht?
Kann da jemand was dazu sagen.


Java:
package dictionarytest;

import java.util.Hashtable;

public class Main {

    public Main() {
        final Hashtable dictionary = new Hashtable();
        dictionary.put("key1", "value1");
        dictionary.put("key2", "value2");
        dictionary.put("key3", "value3");
        dictionary.put("key4", "value4");
        dictionary.put("key5", "value5");
        dictionary.put("key6", "value6");
        System.out.println("Dictionary: " + dictionary);
        
        final Hashtable newHashtable = (Hashtable)dictionary.clone();
        newHashtable.put("key1", "valueNeu");
        System.out.println("dictionary: " + dictionary + ", newHashtable:" + newHashtable);
        }

    public static void main(String[] args) {
        final Main main = new Main();
        }
}
 
Zuletzt bearbeitet:
Die Referenzen der Einträge werden ebenfalls kopiert.
Wenn du allerdings einen eintrag in dictionary änderst, ändert sich der selbe Eintrag in newHashTable. Daher ist das keine deep copy.
 
ob clone() für die Keys und Werte "key1" und Co. echte Kopien erstellt oder die Originalobjekte wiederverwendet, wäre für das Beispiel irrelevant,
dass mindestens die Map neu erstellt wird, kann man doch erwarten,
also wird nach neuer Value-Zuordnung garantiert die Ausgabe kommen wie sie kommt

alles andere wäre ja
> final Hashtable newHashtable = dictionary;
statt
> final Hashtable newHashtable = (Hashtable)dictionary.clone();
dafür brauchts keine clone()-Methode..
 
Eben nicht, probiers mal aus, es kommt folgendes raus:

Code:
Dictionary: {key6=value6, key5=value5, key4=value4, key3=value3, key2=value2, key1=value1}
dictionary: {key6=value6, key5=value5, key4=value4, key3=value3, key2=value2, key1=value1}, newHashtable:{key6=value6, key5=value5, key4=value4, key3=value3, key2=value2, key1=valueNeu}

Nö, verstehs jetzt ehrlich gesagt nicht. Wenn ich clone() mache, dann hab ich meiner Meinung nach 2 Referenzen auf die Hashtable und ob ich mit der einen oder der anderen referenz einen value über einen key ändere müsste ja egal sein, oder?
 
Zuletzt bearbeitet:
Schau Dir doch die Implementierung von clone() in der Hashtable an:
Es wird eine neue Hashtable erzeugt in die geklonte Entries (ebenfalls neu erzeugt) eingefügt werden.
Einzig das Schlüssel-Werte-Paar bleibt erhalten.
Es wird alse eine Art middle-deep-copy gemacht ;-)
 
Zur Veranschaulichung:
Java:
final Hashtable<String, JLabel> origTable = new Hashtable<String, JLabel>();
origTable.put("k1", new JLabel("original"));
origTable.put("k2", new JLabel());
System.out.println("Dictionary key1: " + origTable.get("k1").getText());

final Hashtable<String, JLabel> cloneTable = (Hashtable<String, JLabel>) origTable.clone();
cloneTable.get("k1").setText("ueberschrieben");
System.out.println("Original key1: " + origTable.get("k1").getText());
System.out.println("Clone key1   : " + cloneTable.get("k1").getText());
 
immer gerne angemerkt: nie (Hashtable<String, JLabel>) schreiben, generisch sicher ist das sowieso nicht, (Hashtable) reicht
 
OK, ich nehme es zur Kenntnis, dass es so funktioniert mit JLabel, mit Strings ist das wahrscheinlich ein bisschen anders gelagert, da Strings immutable sind:

Java:
final Hashtable<String, String> origTable = new Hashtable<String, String>();
        origTable.put("k1", new String("original1"));
        origTable.put("k2", new String("original2"));
        System.out.println("Dictionary key1: " + origTable.get("k1"));
        
        final Hashtable<String, String> cloneTable = (Hashtable<String, String>) origTable.clone();
        cloneTable.put("k1", "ueberschrieben");
        System.out.println("Original key1: " + origTable.get("k1"));
        System.out.println("Clone key1   : " + cloneTable.get("k1"));

Man kann also sagen, dass mit einer Hashtable, die nur Strings enthält, eine komplette Deep Copy erzeugt wird!?
 
Man kann also sagen, dass mit einer Hashtable, die nur Strings enthält, eine komplette Deep Copy erzeugt wird!?
Von deep copy würde ich da nicht sprechen. Mit Strings ist das so ne Sache, quasi halb Objekt halb primitiv, auf jeden Fall immutable - wie Du schon angemerkt hast. D.h. Du kannst das "Stringobjekt" in Deiner Hashtable nicht mehr ändern, aber Du kannst - wie in Deinem Codebeispiel - einen neuen String in die geklonte Hashtable stecken. Da die geklonte Hashtable inkl. deren Entries neu erzeugte Objekte sind und der eingefügte String ein neues "Objekt" ist, wirkt sich das nicht auf die originale Hashtable aus.
 
noch ne allgemeine Weisheit: nie new String() schreiben!

und zum JLabel-Beispiel:
wenn du da ein neues JLaben einfügen würdest
cloneTable.put("k2", new JLabel("other"));
dann wäre der Inhalt wieder unterschiedlich

aber es besteht schon ein Unterschied zu String, eben dass man das JLabel (beibehalten und) ändern kann, einen String ist unveränderbar
 
Moin,

weil "bla" schon einen String erzeugt. und new String("bla") erzeugt aus dem neu erzeugten String einen neuen String

verstehe - Danke.
Ist in meinem Fall eh' nur eine Membervariable einer (älteren) Klasse, die mit "private String m_Text = null;" angelegt wird und nach dem "new String()" aus verschiedenen anderen Klassen heraus mit get- und set-Methoden gefükllt wird.

Hier wäre es wohl sinniger, die Deklaration auf "private String m_Text = "";" umzustellen, oder ??

gruß
Klaus
 
>"new String()" aus verschiedenen anderen Klassen heraus mit get- und set-Methoden gefükllt wird.

Verstehe ich nicht?

Umstellen? m_Text gefällt mir nicht aber sonst..?

EDIT:
Java:
    /**
     * Initializes a newly created {@code String} object so that it represents
     * an empty character sequence.  Note that use of this constructor is
     * unnecessary since Strings are immutable.
     */
    public String() {
	this.offset = 0;
	this.count = 0;
	this.value = new char[0];
    }
 
Zuletzt bearbeitet:
Warum? Was spricht dagegen eine Variable mit null zu "initialisieren"? Eventuell ist das ja im späteren Programmablauf relevant

Nein, das ist es hier wohl nicht, da diese Membervariable (die Klasse stellt eine Art Report zu Verfügung) immer nur gefüllt und ausgelesen, aber nie auf Inhalt, oder besser: auf 'null', wird!

Eigentlich wird das in diesem Projekt überall so gehandelt, aber ich bin noch in der Einarbeitungphase und habe - dank fehlender Doku - an manchen Stellen noch so meine Verständnisprobleme ..... ;(

Danke und Gruß
Klaus
 
wenn man andere vielleicht komplizierte Projekte übernimmt, dann vorsichtig mit Änderungen,
in Extremfällen kann new String() schon zum Einsatz kommen,

es reicht wenn man weiß/ beachtet:
solange ich
String s = "x";
schreiben kann und mir kein triftiger Grund einfällt, sollte ich es unterlassen
String s = new String("x");
zu schreiben 😉
 
wenn man andere vielleicht komplizierte Projekte übernimmt, dann vorsichtig mit Änderungen,
in Extremfällen kann new String() schon zum Einsatz kommen,

es reicht wenn man weiß/ beachtet:
solange ich
String s = "x";
schreiben kann und mir kein triftiger Grund einfällt, sollte ich es unterlassen
String s = new String("x");
zu schreiben 😉

ok, Danke .... 😉

Soweit ich das sehe, wird das "new String()" nur im Konstruktor verwendet und das Objekt wirklich zu instantiieren resp. in einer Reset-Funktion, um die Membervariable zu leeren .....
Ich werde mir das bei Gelegenheit mal in Ruhe im Debugger anschauen müssen ...

[OFFTOPIC]
Wird Hansa (ich vermute mal Rostock) denn DIESES Jahr Meister ???:L😀
[/OFFTOPIC]

Gruß aus OS
Klaus
 

Zurück
Oben