926 Stimmen

Wie kopiere ich ein Objekt in Java?

Betrachten Sie den folgenden Code:

DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // gibt 'foo' aus

DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // gibt 'foo' aus

dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // gibt 'bar' aus, aber es sollte 'foo' ausgeben

Also möchte ich dum nach dumtwo kopieren und dum ändern, ohne dumtwo zu beeinflussen. Aber der obige Code tut das nicht. Wenn ich etwas in dum ändere, geschieht die gleiche Änderung auch in dumtwo.

Ich vermute, wenn ich dumtwo = dum sage, kopiert Java nur die Referenz. Gibt es also einen Weg, eine frische Kopie von dum zu erstellen und sie dumtwo zuzuweisen?

34voto

Peter Punkte 854

Ich verwende die JSON-Bibliothek von Google, um sie zu serialisieren, dann erstelle ich eine neue Instanz des serialisierten Objekts. Es führt eine Tiefenkopie mit einigen Einschränkungen durch:

  • es dürfen keine rekursiven Referenzen vorhanden sein

  • es kopiert keine Arrays verschiedener Typen

  • Arrays und Listen sollten typisiert sein, sonst findet es die Klasse nicht, um eine Instanz zu erstellen

  • Sie müssen möglicherweise Zeichenfolgen in einer von Ihnen selbst deklarierten Klasse kapseln

Ich benutze diese Klasse auch, um Benutzereinstellungen, Fenster und dergleichen zu speichern, um sie zur Laufzeit neu zu laden. Es ist sehr einfach zu bedienen und effektiv.

import com.google.gson.*;

public class SerialUtils {

//___________________________________________________________________________________

public static String serializeObject(Object o) {
    Gson gson = new Gson();
    String serializedObject = gson.toJson(o);
    return serializedObject;
}
//___________________________________________________________________________________

public static Object unserializeObject(String s, Object o){
    Gson gson = new Gson();
    Object object = gson.fromJson(s, o.getClass());
    return object;
}
       //___________________________________________________________________________________
public static Object cloneObject(Object o){
    String s = serializeObject(o);
    Object object = unserializeObject(s,o);
    return object;
}
}

1 Stimmen

Dies funktioniert großartig. Aber Vorsicht, wenn Sie versuchen, etwas wie List zu klonen. Es wird Fehler geben, meine Integers wurden zu Doubles, 100.0 umgewandelt. Es hat eine lange Zeit gedauert, bis ich verstanden habe, warum sie so sind. Die Lösung bestand darin, die Integers einzeln zu klonen und sie nacheinander der Liste hinzuzufügen.

24voto

Chrisb Punkte 729

Ja, du machst nur eine Referenz auf das Objekt. Du kannst das Objekt klonen, wenn es Cloneable implementiert.

Sieh dir diesen Wiki-Artikel über das Kopieren von Objekten an.

Hier verweisen: Objektkopieren

18voto

Teja Maridu Punkte 477

Füge Cloneable und den folgenden Code zu deiner Klasse hinzu

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

Verwende dies clonedObject = (YourClass) yourClassObject.clone();

18voto

abbas Punkte 5423

Tiefe Klonierung ist die Lösung, die die Implementierung des Cloneable-Interfaces und das Überschreiben der clone()-Methode erfordert.

public class DummyBean implements Cloneable {

   private String dummy;

   public void setDummy(String dummy) {
      this.dummy = dummy;
   }

   public String getDummy() {
      return dummy;
   }

   @Override
   public Object clone() throws CloneNotSupportedException {
      DummyBean cloned = (DummyBean)super.clone();
      cloned.setDummy(cloned.getDummy());
      // das obige gilt im Falle von primitiven Datentypen wie String
      // jedoch im Falle von nicht primitiven Datentypen
      // cloned.setNonPrimitiveType(cloned.getNonPrimitiveType().clone());
      return cloned;
   }
}

Sie werden es so aufrufen DummyBean dumtwo = dum.clone();

4 Stimmen

dummy, ein String, ist unveränderlich, du brauchst ihn nicht zu kopieren

13voto

Qamar Punkte 4483

Dies funktioniert auch. Angenommen, Modell

class UserAccount{
   public int id;
   public String name;
}

Zuerst hinzufügen compile 'com.google.code.gson:gson:2.8.1' zu Ihrem app>gradle & synchronisieren. Dann

Gson gson = new Gson();
updateUser = gson.fromJson(gson.toJson(mUser),UserAccount.class);

Sie können die Verwendung eines Feldes ausschließen, indem Sie das Schlüsselwort transient nach dem Zugriffsmodifizierer verwenden.

Hinweis: Das ist eine schlechte Praxis. Es wird auch nicht empfohlen, Cloneable oder JavaSerialization zu verwenden. Es ist langsam und fehlerhaft. Schreiben Sie einen Kopierkonstruktor für die beste Leistung weiterlesen.

So etwas wie

class UserAccount{
        public int id;
        public String name;
        //Leerer Konstruktor
        public UserAccount(){}
        //Parameterisierter Konstruktor
        public UserAccount(int id, String name) {
            this.id = id;
            this.name = name;
        }

        //Kopierkonstruktor
        public UserAccount(UserAccount in){
            this(in.id,in.name);
        }
    }

Testergebnisse von 90000 Iterationen:
Zeile UserAccount clone = gson.fromJson(gson.toJson(aO), UserAccount.class); dauert 808ms

Zeile UserAccount clone = new UserAccount(aO); dauert weniger als 1ms

Schlussfolgerung: Verwenden Sie gson, wenn Ihr Chef verrückt ist und Sie Geschwindigkeit bevorzugen. Verwenden Sie den zweiten Kopierkonstruktor, wenn Sie Qualität bevorzugen.

Sie können auch den Kopierkonstruktor-Code Generator Plugin in Android Studio verwenden.

0 Stimmen

Warum hast du es vorgeschlagen, wenn es eine schlechte Praxis ist?

0 Stimmen

Danke @ParthMehrotra, jetzt verbessert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X