Heim  >  Artikel  >  Java  >  Java-Verbesserung Teil 5 -----Serialisierung zum Kopieren von Objekten verwenden

Java-Verbesserung Teil 5 -----Serialisierung zum Kopieren von Objekten verwenden

黄舟
黄舟Original
2017-02-09 13:39:071150Durchsuche

Wir wissen, dass Klassen, die diese Schnittstelle implementieren, in Java kopiert werden können. Gleichzeitig erfolgt das Kopieren im Speicher schneller als das direkte Generieren von Objekten Neu, insbesondere bei der Generierung großer Objekte, ist die Leistungsverbesserung sehr offensichtlich. Wir wissen jedoch, dass Kopien in tiefe Kopien und flache Kopien unterteilt werden, aber flache Kopien weisen das Problem einer unvollständigen Kopie von Objektattributen auf. Informationen zu Deep Copy und Shallow Copy finden Sie hier: Schrittweise Analyse von Shallow Copy und Deep Copy von Java

1. Shallow Copy-Problem

Schauen wir uns zunächst den folgenden Code an:

public class Person implements Cloneable{  
    /** 姓名 **/  
    private String name;  
      
    /** 电子邮件 **/  
    private Email email;  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public Email getEmail() {  
        return email;  
    }  
  
    public void setEmail(Email email) {  
        this.email = email;  
    }  
      
    public Person(String name,Email email){  
        this.name  = name;  
        this.email = email;  
    }  
      
    public Person(String name){  
        this.name = name;  
    }  
  
    protected Person clone() {  
        Person person = null;  
        try {  
            person = (Person) super.clone();  
        } catch (CloneNotSupportedException e) {  
            e.printStackTrace();  
        }  
          
        return person;  
    }  
}  
  
public class Client {  
    public static void main(String[] args) {  
        //写封邮件  
        Email email = new Email("请参加会议","请与今天12:30到二会议室参加会议...");  
          
        Person person1 =  new Person("张三",email);  
          
        Person person2 =  person1.clone();  
        person2.setName("李四");  
        Person person3 =  person1.clone();  
        person3.setName("王五");  
          
        System.out.println(person1.getName() + "的邮件内容是:" + person1.getEmail().getContent());  
        System.out.println(person2.getName() + "的邮件内容是:" + person2.getEmail().getContent());  
        System.out.println(person3.getName() + "的邮件内容是:" + person3.getEmail().getContent());  
    }  
}  
--------------------  
Output:  
张三的邮件内容是:请与今天12:30到二会议室参加会议...  
李四的邮件内容是:请与今天12:30到二会议室参加会议...  
王五的邮件内容是:请与今天12:30到二会议室参加会议...

Definieren Sie in dieser Anwendung zunächst eine E-Mail und senden Sie die E-Mail dann an Zhang San, Li Si und Wang Wu. Da sie dieselbe E-Mail verwenden und nur unterschiedliche Namen haben, verwenden Sie die Objektklasse von Zhang San, die kopiert werden kann die Objekte „John Four“ und „Wang Five“ und ändern dann den Namen. Bisher ist am Programm nichts auszusetzen, aber wenn Zhang San 30 Minuten im Voraus eintreffen muss, ändern wir den Inhalt der E-Mail:

public class Client {  
    public static void main(String[] args) {  
        //写封邮件  
        Email email = new Email("请参加会议","请与今天12:30到二会议室参加会议...");  
          
        Person person1 =  new Person("张三",email);  
          
        Person person2 =  person1.clone();  
        person2.setName("李四");  
        Person person3 =  person1.clone();  
        person3.setName("王五");  
          
        person1.getEmail().setContent("请与今天12:00到二会议室参加会议...");  
          
        System.out.println(person1.getName() + "的邮件内容是:" + person1.getEmail().getContent());  
        System.out.println(person2.getName() + "的邮件内容是:" + person2.getEmail().getContent());  
        System.out.println(person3.getName() + "的邮件内容是:" + person3.getEmail().getContent());  
    }  
}

Hier verwenden wir auch das Objekt von Zhang San realisierte die Kommunikation zwischen Li Si und Li Wang Wu und änderte schließlich den Inhalt von Zhang Sans E-Mail in: Bitte kommen Sie heute um 12:00 Uhr in den zweiten Konferenzraum, um an der Besprechung teilzunehmen ... Aber das Ergebnis ist:

张三的邮件内容是:请与今天12:00到二会议室参加会议...  
李四的邮件内容是:请与今天12:00到二会议室参加会议...  
王五的邮件内容是:请与今天12:00到二会议室参加会议...

Hier fragen wir uns, warum auch der Inhalt der E-Mails von Li Si und Wang Wu geändert wurde? Es gibt Einwände, wenn sie gebeten werden, 30 Minuten früher anzureisen!

Tatsächlich liegt der Schlüssel zum Problem in der clone()-Methode. Wir wissen, dass die clone()-Methode die clone()-Methode der Object-Klasse verwendet, aber diese Methode hat einen Fehler Es werden nicht alle Attribute des Objekts kopiert, sondern selektiv kopiert. Die Grundregeln lauten wie folgt:

1. Basistyp

Wenn die Variable ein Basistyp ist, kopieren Sie ihren Wert, z int, float warte.

2. Objekt

Wenn die Variable ein Instanzobjekt ist, kopieren Sie ihre Adressreferenz, was bedeutet, dass das neue Objekt und das ursprüngliche Objekt die Instanzvariable gemeinsam nutzen.

3. String

Wenn die Variable ein String ist, kopieren Sie ihre Adressreferenz. Bei einer Änderung wird jedoch eine neue Zeichenfolge aus dem Zeichenfolgenpool neu generiert, und das ursprüngliche Ziducheng-Objekt bleibt unverändert.

Basierend auf den oben genannten Regeln können wir das Problem leicht finden. Die drei haben ein gemeinsames Objekt. Wenn Zhang San den Inhalt der E-Mail ändert, ändern sie ihn auch oben erscheint die Situation. Wir können diese Situation immer noch lösen. Wir müssen nur ein neues Objekt in der clone()-Methode erstellen und dann verweist Zhang San auf das Objekt:

protected Person clone() {  
        Person person = null;  
        try {  
            person = (Person) super.clone();  
            person.setEmail(new Email(person.getEmail().getObject(),person.getEmail().getContent()));  
        } catch (CloneNotSupportedException e) {  
            e.printStackTrace();  
        }  
          
        return person;  
    }

Also: Flache Kopie ist nur ein von Java bereitgestellter Typ Einfacher Kopiermechanismus, nicht einfach direkt zu verwenden.

Es gibt immer noch ein Problem mit der oben genannten Lösung. Wenn in unserem System eine große Anzahl von Objekten durch Kopieren generiert wird und wir für jede Klasse eine clone()-Methode schreiben, werden auch tiefe Kopien erstellt Erforderlich, erstellen Sie eine große Anzahl neuer Objekte. Dieses Projekt ist sehr groß. Hier können wir die Serialisierung verwenden, um die Objekte zu kopieren.

2. Serialisierung zum Kopieren von Objekten verwenden

Wie verwende ich Serialisierung zum Kopieren von Objekten? Dies ist relativ einfach durch Kopieren des Bytestreams in den Speicher zu erreichen. Schreiben Sie das übergeordnete Objekt in einen Byte-Stream und lesen Sie es dann aus dem Byte-Stream aus, sodass Sie ein neues Objekt erstellen können und es kein Problem mit der gemeinsamen Nutzung von Referenzen zwischen dem neuen Objekt und dem übergeordneten Objekt gibt. Implementieren Sie wirklich eine tiefe Kopie Objekte.

public class CloneUtils {  
    @SuppressWarnings("unchecked")  
    public static <T extends Serializable> T clone(T obj){  
        T cloneObj = null;  
        try {  
            //写入字节流  
            ByteArrayOutputStream out = new ByteArrayOutputStream();  
            ObjectOutputStream obs = new ObjectOutputStream(out);  
            obs.writeObject(obj);  
            obs.close();  
              
            //分配内存,写入原始对象,生成新对象  
            ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());  
            ObjectInputStream ois = new ObjectInputStream(ios);  
            //返回生成的新对象  
            cloneObj = (T) ois.readObject();  
            ois.close();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return cloneObj;  
    }  
}

Objekte, die diese Toolklasse verwenden, müssen die Serializable-Schnittstelle implementieren, andernfalls gibt es keine Möglichkeit, das Klonen zu erreichen.

public class Person implements Serializable{  
    private static final long serialVersionUID = 2631590509760908280L;  
  
    ..................  
    //去除clone()方法  
  
}  
  
public class Email implements Serializable{  
    private static final long serialVersionUID = 1267293988171991494L;  
      
    ....................  
}

Daher können Objekte, die diese Werkzeugklasse verwenden, das Klonen von Objekten erreichen, solange sie die Serializable-Schnittstelle implementieren und es nicht erforderlich ist, die Cloneable-Schnittstelle zu erben, um die clone()-Methode zu implementieren.

public class Client {  
    public static void main(String[] args) {  
        //写封邮件  
        Email email = new Email("请参加会议","请与今天12:30到二会议室参加会议...");  
          
        Person person1 =  new Person("张三",email);  
          
        Person person2 =  CloneUtils.clone(person1);  
        person2.setName("李四");  
        Person person3 =  CloneUtils.clone(person1);  
        person3.setName("王五");  
        person1.getEmail().setContent("请与今天12:00到二会议室参加会议...");  
          
        System.out.println(person1.getName() + "的邮件内容是:" + person1.getEmail().getContent());  
        System.out.println(person2.getName() + "的邮件内容是:" + person2.getEmail().getContent());  
        System.out.println(person3.getName() + "的邮件内容是:" + person3.getEmail().getContent());  
    }  
}  
-------------------  
Output:  
张三的邮件内容是:请与今天12:00到二会议室参加会议...  
李四的邮件内容是:请与今天12:30到二会议室参加会议...  
王五的邮件内容是:请与今天12:30到二会议室参加会议...

Das Obige ist der Inhalt von Java Improvement Teil 5 -----Serialisierung zum Kopieren von Objekten verwenden. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn). !


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn