8 Stimmen

Wird clone() wirklich jemals verwendet? Was ist mit defensivem Kopieren in Gettern/Settern?

Verwenden die Leute praktisch immer defensive Getter/Setter? Meiner Meinung nach beabsichtigen Sie in 99 % der Fälle, dass das Objekt, das Sie in einem anderen Objekt festlegen, eine Kopie desselben Objektverweises ist, und Sie beabsichtigen, dass Änderungen, die Sie daran vornehmen, auch in dem Objekt vorgenommen werden, in dem es festgelegt wurde. Wenn Sie setDate ( Date dt ) und dt später ändern, wen interessiert das? Es sei denn, ich will einige grundlegende unveränderliche Daten Bean, die nur Primitive und vielleicht etwas Einfaches wie ein Datum hat, ich nie verwenden es.

Was das Klonen anbelangt, so gibt es Probleme damit, wie tief oder flach die Kopie ist, so dass es irgendwie "gefährlich" erscheint, zu wissen, was herauskommt, wenn man ein Objekt klont. Ich glaube, ich habe nur Folgendes verwendet clone() ein- oder zweimal, und zwar, um den aktuellen Zustand des Objekts zu kopieren, da ein anderer Thread (d.h. eine andere HTTP-Anfrage, die auf dasselbe Objekt in der Sitzung zugreift) es ändern könnte.

Edit - Eine Bemerkung, die ich unten gemacht habe, ist eher die Frage:

Aber andererseits haben Sie das Datum geändert, also sind Sie selbst schuld, daher die ganze Diskussion über den Begriff "defensiv". Wenn der gesamte Anwendungscode von einer kleinen bis mittelgroßen Gruppe von Entwicklern selbst kontrolliert wird, reicht es dann aus, die Klassen zu dokumentieren, anstatt Objektkopien zu erstellen? Oder ist dies nicht notwendig, da man immer davon ausgehen sollte, dass etwas NICHT kopiert wird, wenn man einen Setter/Getter aufruft?

0voto

Salandur Punkte 6351

Ich mag die clone()-Methode nicht, da immer ein Typ-Cast erforderlich ist. Aus diesem Grund verwende ich meistens den Copy-Constructor. Er sagt klarer, was er tut (neues Objekt) und man hat viel Kontrolle darüber, wie er sich verhält oder wie tief die Kopie ist.

Bei meiner Arbeit machen wir uns keine Gedanken über defensive Programmierung, obwohl das eine schlechte Angewohnheit ist. Die meiste Zeit geht es gut, aber ich denke, ich werde es mir genauer ansehen.

0voto

Eine Sache, die ich bei einer "Defensivkopie-Diskussion" immer vermisse, ist der Leistungsaspekt. Diese Diskussion ist IMHO ein perfektes Beispiel für Leistung vs. Lesbarkeit/Sicherheit/Robustheit.

Verteidigungsexemplare eignen sich hervorragend für Ropbust Ode. Aber wenn Sie sie in einem zeitkritischen Teil Ihrer Anwendung verwenden, kann das ein großes Leistungsproblem darstellen. Wir hatten diese Diskussion kürzlich, als ein Datenvektor seine Daten in einem double[] values speicherte. getValues() gab values.clone() zurück. In unserem Algorithmus wurde getValues() aufgerufen für beaucoup von verschiedenen Objekten. Als wir uns fragten, warum die Ausführung dieses einfachen Codes so lange dauerte, untersuchten wir den Code - ersetzten die Rückgabewerte.clone() durch Rückgabewerte und plötzlich war unsere Gesamtausführungszeit auf weniger als 1/10 des ursprünglichen Wertes gesunken. Nun - ich brauche wohl nicht zu sagen, dass wir uns entschieden haben, die Defensivität zu überspringen.

Anmerkung: Ich bin nicht gegen Kopien im Allgemeinen. Aber benutze dein Gehirn, wenn du klonst()ing!

0voto

Frank Hellwig Punkte 11

Ich habe begonnen, die folgende Praxis anzuwenden:

  1. Erstellen Sie Kopierkonstruktoren in Ihren Klassen, aber machen Sie sie geschützt. Der Grund dafür ist, dass die Erstellung von Objekten mit dem new-Operator zu verschiedenen Problemen bei der Arbeit mit abgeleiteten Objekten führen kann.

  2. Legen Sie eine Copyable-Schnittstelle wie folgt an:

     public interface Copyable<T> {
            public T copy();
     }

Die Kopiermethode von Klassen, die Copyable implementieren, muss den geschützten Kopierkonstruktor aufrufen. Abgeleitete Klassen können dann super.Xxx(obj_to_copy); aufrufen, um den Kopierkonstruktor der Basisklasse zu nutzen und bei Bedarf zusätzliche Funktionen hinzuzufügen.

Die Tatsache, dass Java die kovariante Rückgabeart macht dies möglich. Abgeleitete Klassen implementieren einfach die copy()-Methode nach Bedarf und geben einen typsicheren Wert für ihre jeweilige Klasse zurück.

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