Java Grundkurs 3: Generische Programmierung, Datenströme, Datumsrechnung

Flache oder tiefe Kopie

Testen Sie unsere 1983 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
Lassen Sie sich in diesem Video den Unterschied zwischen Shallow Copy und Deep Copy erklären.

Transkript

In diesem Video werde ich Ihnen zwei Fachbegriffe erklären, nämlich das sogenannte Shallow Copy und das Deep Copy. Die deutsche Übersetzung für die beiden Fachbegriffe lautet flaches und tiefes Kopieren. In unserem Beispielprogramm haben wir für unsere Katze die Methode Clone eingebaut. Hierfür brauchten wir bislang lediglich das Shallow Copy. Das haben wir deswegen eingesetzt, da es sich bei den Eigenschafts-Feldern der Katze lediglich um elementare Variablen des Datentyps Int handelte. Elementare Variablen werden bei Value zugewiesen. Dabei handelt es sich stets um eine Kopie der Datenbehälter Was wäre aber, wenn wir die Messungswerte in eine eigene Klasse verschieben und diese kopieren wollten. Wir schauen uns das mal an, iin dem wir eine weitere Klasse mit dem Namen Messung definieren. Ich kopiere die Klasse Katze ganz einfach mal als Klasse Messung über Strg + C, Strg + V. So und innerhalb der Klasse Messung muss ich auch noch die Tostring Methode anpassen, denn sonst stimmt die Ausgabe nicht. Dann sind wir mit der Klasse Messung fertig. Jetzt gehe ich rüber zur Klasse Katze. Jetzt passe ich die Klasse Katze an, denn die braucht nur noch die Klasse Messung einzubinden. Also hier oben private Messung. Ich habe also die beiden Eigenschafts Felder groesse und gewicht entfernt und ein neues Eigenschafts-Feld hinzugefügt mit dem Namen messung. Eine neue Objektvariable. Jetzt muss ich auch noch dafür sorgen, dass die Übergabeparameter und die Methoden überall auch meine Änderung berücksichtigen. Also messung als Übergabeparameter im Konstruktor und hier, innerhalb des Konstruktors muss ich dann einer messung den Übergabeparameter zuweisen Die Getter und Setter erzeuge ich neu. Die alten sind ja falsch, die brauche ich also komplett neu. Source Generate Getters und Setters wird mir dann die Getter und Setter liefern. So, dann bin ich hiermit fertig und jetzt muss ich mich um die Clone Methode kümmern. Hier erzeuge ich ja ein neues Objekt des Typs Katze, weise es der Variablen Clone zu und das Eigenschafts-Feld, das ich nun kopieren muss, ist das Eigenschafts-Feld vom Datentyp Messung. Also set.Messung ist gleich (messung) und somit habe ich dann die Clone Methode fertig gestellt und jetzt ist meine To String Methode natürlich noch verkehrt. Katze und hier unten muss dann messung stehen. Und der Wert muss auch messung sein. So die Methode To String ist fertig Die Klasse ist komplett. Jetzt gehe ich in die Startklasse App hinein, denn dort muss ich die Erzeugung der Variablen Katze1 anpassen. Aber das ist ganz einfach. Ich geh einfach hin und nutze den Konstruktor, der eine Messung als Übergabeparameter entgegennimmt und erzeuge ein Objekt des Typs Messung mit den beiden Werten Groesse und Gewicht und übergebe dem Konstruktor dann die Messung und schon bin ich dann hiermit fertig. Jetzt gebe ich mir das Ergebnis einmal aus. Wie Sie sehen, haben wir tatsächlich etwas kopiert. Die beiden Objekte sehen gleich aus. Aber was genau haben wir bewirkt? Ich gehe wieder in die Methode Clone zurück, wo ich Ihnen zeigen kann, was wir nun falsch gemacht haben. Also Katze Clone. Jetzt gehe ich hier in die Zeile 24. Wenn wir an dieser Stelle die Methode setMessung aufrufen, übergeben wir ihr die Variable Messung und zwar handelt es sich bei Java ja bei einer Behandlung eines komplexen Datentyps immer um einen Zeiger. Das hatte ich ja erwähnt. Und dieser Zeiger zeigt auf eine bestimmte Adresse im Speicher. Und hiermit haben wir an dieser Stelle die Adresse, auf die der Zeiger Messung vom aktuellen Objekt Zeigt in den Zeiger Messung des Clones kopiert. Dadurch zeigt der Zeiger Messung des Clones nun ebenso auf die Speicheradresse des Messungsobjekts von hier oben. Gut, beide Zeiger zeigen also auf ein und das gleiche Objekt. Dies können wir uns genauer anschauen, indem wir uns die Adresse, auf die der Zeiger zeigt, als Hash Code ausgeben lassen. In der Startklasse App, werde ich mir die Speicheradressen anzeigen lassen, auf die die Messungsvariablen zeigen. Beziehungsweise, ich lasse mir eine Repräsentation der Speicheradressen anzeigen. Das geht wie folgt. Ich schreibe wieder System.out.println und hier besorge ich mir die Variable katze1, hole mir das Messungsobjekt und führe die Methode hashCode aus Und das Gleiche mache ich auch mit der zweiten Katze. Also mit der Variablen katze2. Und das Programm führe ich jetzt einmal aus. So und wie Sie sehen, hier unten erhalten wir den gleichen hashcode. Wir haben also die Adresse, auf die der Zeiger Messung, der Katze1 zeigt, in den Zeiger Messung der Katze2 kopiert. Aber das ist nicht das Ergebnis, das wir haben wollen. Denn obwohl wir zwei unterschiedliche Zeiger haben, handelt es sich um eine einzige Speicheradresse, beziehungsweise um ein einziges Objekt, auf das beide Zeiger zeigen. Wir brauchen aber ein zweites Objekt. Und diesem Objekt müssen wir die Eigenschafts-Felder es ersten Objekts hinüberkopieren. Die Lösung ist aber ganz einfach. Denn wir müssen hierzu einfach in die Methode Clone hineingehen und das dann entsprechend umsetzen. Und zwar brauchen wir bloß von der Messung der aktuellen Katze die Methode clone aufzurufen. Und hier brauchen wir auch einen Cast, denn in dieser Methode Clone, der Klasse Messung, haben wir ja bereits dafür gesorgt, dass ein neues Messungsobjekt erzeugt wird. Dass also ein anderer Speicherbereich, ein zweiter erzeigt wird und dort dann eben diese elementaren Variablen, das heißt diese Behälter mit den primitiven Datentypen, dass die dort hineinkopiert werden. Also so funktioniert es. Und dass kann ich jetzt auch nochmal ausprobieren. Ich klicke auf Play und jetzt sehen Sie, dass wir hier unterschiedliche hashCodes haben. Das Kopieren geht jetzt also eine Ebene tiefer. Denn in der Methode Clone der Klasse Messung erzeuge ich ja ein neues Objekt und weise diesem die primitiven Variablen Groesse und Gewicht zu. Weil wir das Kopieren über zwei Ebenen hinweg tiefer durchführen, spricht man vom sogenannten Deep Copy, wohingegen das Kopieren über eine Ebene als Shallow Copy, also als flaches Kopieren bezeichnet wird. Der Unterschied besteht also darin, dass beim Deep Copy in der Clone Methode auch wieder Clone Methoden der inneren Elemente aufgerufen werden. Genau das machen wir hier in der Klasse Katze, indem wir bei der Messung die Methode Clone aufrufen Wenn man es nun ganz genau nimmt, dann ist es ja so, dass wir im Grunde genommen nur bei der Clone Methode der Katze einen Deep Copy durchführen, während wir in der Klasse Messung mit einem Shallow Copy auskommen. Weil es sich bei den Eigenschafts-Feldern dort ja um elementare Variablen handelt. Allerdings ist dies nicht der einzige Fall, wann wir mit einem Shallow Copy auskommen. Denn auch bei Strings und auch bei Wrapper Klassen, kann auf das Deep Copy verzichtet werden. Der Grund hierfür ist, dass die inneren Werte der String und Wrapper Variablen unveränderbar sind. So können wir auch bei diesen Datentypen auf das Deep Copy verzichten. Und genau das schauen wir uns jetzt mal an, indem wir unser Beispielprogramm erweitern und zwar werden wir beide Variablen groesse und gewicht bei beiden werden wir jetzt den Datentypen abändern zu einer Wrapper Klasse und zwar zu der Wrapper Klasse Double. So und aufgrund essen muss ich jetzt den Constructor und die Getter und Setter Methoden anpassen, also überall wo elementare Datentypen angezeigt werden. Das muss ich jetzt dann ändern. Hier auch und dort in der Setter Methode vom Gewicht, das war’s. Also Constructor, Getter und Setter und wir sind fertig. Dann speichere ich die Klasse Messung noch ab. Um das Beispiel dann auch mit einer Objekt-Variablen des Typs String zu zeigen, werde ich in der Klasse Katze auch noch eine weitere Objekt-Variable einbauen, die vom Typ String sein sollte. Also private String. Und dies soll dann der Name der Katze sein. Hier brauche ich jetzt wieder Getter und Setter. Also gehe ich ins Hauptmenü auf Source und dann Generate Getters und Setters und selektiere das Feld Name und das soll mir ja am besten unterhalb des Konstruktors hinzugefügt werden Und dann klicke ich auf OK und hier sehen Sie dann die neuen Getter und Setter Methoden. Und jetzt muss ich natürlich auch die Clone Methode anpassen und auch die toString Methode also gehe ich jetzt hier hin und setze den Namen des Clones auf den Namen der aktuellen Klasse, also des aktuellen Objekts und auch hier unten bei der toString Methode kopiere ich jetzt einfach mal diesen Teil hier rüber. name = name, das ist neu. Und messung = messung, das lass ich so stehen Ja und ansonsten könnten wir auch einen weiteren Konstruktor brauchen, beziehungsweise einen neuen Konstruktor. Ich wandle diesen Konstruktor um und baue dort einen weiteren Übergabeparameter ein, damit wir bei der Erzeugung des neuen Objekts einfach nur einen einzigen Konstruktor brauchen und sonst die Setter Methoden nicht mehr bemühen brauchen. So und dann speichere ich die Klasse ab und gehe dann rüber in die Klasse App, denn dort muss ich noch etwas anpassen und zwar muss ich hier dann den Namen hinzufügen der Katze. Die Katze soll Pinki heißen. Und ansonsten passt es. Und das Beispiel probiere ich auch noch aus. So und das hat funktioniert. Wir haben jetzt zwei unterschiedliche Objekte, also zwei unterschiedliche Bereiche im Speicher für die Katze aber auch zwei unterschiedliche Speicherbereiche für die Messung. Das sieht man hier an den hashCodes. Und somit ist uns das Deep Copy gelungen, obwohl wir mit Objektdatentypen gearbeitet haben Nur dass es sich dabei um Strings und Wrapper Klassen gehandelt hat und es somit genauso funktioniert, wir mit den elementaren Datentypen, wo wir mit Shallow Copy gearbeitet haben. Das heißt wir mussten keine Clone Methode ausführen. Insofern haben sie nun das Deep Copy und das Shallow Copy, sowohl mit den Elementaren Datentypen, als auch mit den Objekt Datentypen komplett gelernt. In diesem Video habe ich Ihnen den Unterschied zwischen dem Shallow Copy und dem Deep Copy erklärt. Bei dem Shallow Copy erzeugen wir ein neues Objekt, das wir als Kopie benötigen. Alle Eigenschafts-Felder des Quellobjekts werden dabei lediglich in das Zielobjekt kopiert, wohingegen wir bei dem Deep Copy die Clone Methode des Eigenschafts-Feldes aufrufen, damit auch dort wiederum ein neues Objekt für die zweite Ebene erzeugt wird. Während wir bei einer Klasse, in der die Eigenschafts-Felder nur mit den elementaren Datentypen Strings oder Wrapper Klassen typisiert sind, mit dem Shallow Copy auskommen, müssen wir bei Eigenschafts-Feldern anderer Datentypen mit einem Deep Copy arbeiten.

Java Grundkurs 3: Generische Programmierung, Datenströme, Datumsrechnung

Steigen Sie tiefer in die Java-Programierung ein und lernen Sie den Umgang mit generischen Typen, Lamda-Ausdrücken, DAtenströmen und mit Datums- und Zeitberechnung.

5 Std. 24 min (47 Videos)
Derzeit sind keine Feedbacks vorhanden...
 
Hersteller:
Software:
Exklusiv für Abo-Kunden
Erscheinungsdatum:09.10.2016

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!