Hat das Klonen eine Leistungsverbesserung gegenüber Bauer / Factory-Methoden zur Verfügung stellen?

StackOverflow https://stackoverflow.com/questions/663079

Frage

Ich bin maintaing eine ältere Java Code-Basis (JVM 1.4), die das Klonen als Alternative zu verwenden scheint Instanziierung zu widersprechen, vermute ich als Performance-Optimierung. Hier ist ein konstruiertes Beispiel:

public class Foo {
  private SomeObject obj; // SomeObject implements Cloneable
  public Foo() {
    obj = new SomeObject();
    obj.setField1("abc"); // these fields will have the same value every time
    obj.setField2("def");
  }
  public void doStuff() {
    SomeObject newObj = obj.clone(); // clone it instead of using a factory method
    // do stuff with newObj
  }
}

Die üblichen Warnungen über vorzeitige Optimierung ungeachtet, war dies eigentlich eine empfohlene Idiom irgendwann?

War es hilfreich?

Lösung

Ein Grund clone() anstelle des Copykonstruktor oder eine Fabrik Methode aufzurufen ist, dass keiner der anderen Optionen zur Verfügung steht.

clone() Implementierung eine flache Objektkopie auszuführen (tiefere Kopie ist mehr beteiligt) ist trivial im Vergleich zu einem Copy-Konstruktor oder eine Fabrik Verfahren implementiert die gleiche Operation durchzuführen. Zur Umsetzung clone() muss eine Klasse einfach die Cloneable-Schnittstelle implementieren und überschreiben Methode clone() mit einem, dem super.clone() ruft die in der Regel Object.clone() aufruft. Object.clone() Kopien jede Eigenschaft des ursprünglichen Objekts in die entsprechende Eigenschaft des Duplikats, wodurch eine flache Kopie erzeugt wird.

Obwohl die Umsetzung clone() einfach ist, ist es immer noch leicht zu vergessen, Cloneable zu implementieren. Folglich ein Objekt ein potentielles Risiko der Verwendung von clone() zu duplizieren ist, dass, wenn die Klasse des Objekts tut Vernachlässigung Cloneable zu implementieren und clone() ruft Object.clone() entweder direkt oder indirekt, wird es CloneNotSupportedException werfen.

Sehen Sie dieses Codebeispiel und eine vorherige Diskussion auf die schlechtes Design die Cloneable Schnittstelle.

Andere Tipps

Vermutlich wollten sie eine Kopie. Vielleicht wollen sie es an eine andere Funktion zu übergeben, und kann nicht sicher sein, dass diese Funktion nicht ändern. Es ist ein Weg, sicherzustellen, dass das Verfahren doStuff () aufgerufen, const in Bezug auf den Zustand der Foo-Objekt es ist.

Ein großes Problem mit Kopierkonstruktoren ist, dass die Art des Objekts zum Zeitpunkt der Kompilierung bekannt sein muss. Wenn eine vererbbare Klasse eine Kopie Konstruktor unterstützt, und der Konstruktor ist ein abgeleitete Klasse-Objekt übergeben, erzeugt der Konstruktor ein Basis-Klasse-Objekt, deren Basis-Klasse Eigenschaften im Allgemeinen jene des übergebene Objekt übereinstimmen, aber das neue Objekt gewonnen‘ t alle Funktionen unterstützt, die in dem übergebene Objekt vorhanden waren, die nicht in der Basisklasse waren.

Es ist möglich, dieses Problem etwas zu lösen, indem eine Kopie Konstruktor „geschützt“ zu machen, und in jeder abgeleiteten Klasse eine überwindbare Fabrik Kopiermethode, die diese Klasse eigenen Kopierkonstruktor aufruft, die wiederum den Copykonstruktor seiner Basisklasse ruft . Jede abgeleitete Klasse wird eine Kopie Konstruktor und eine Überschreibung des Kopiermethode benötigen, aber, ob es irgendwelche neue Felder hinzufügt. Wenn die Fall-Klasse verwendet „Klon“, dieser zusätzliche Code beseitigt werden kann.

Es kann eine Performance-Optimierung, je nachdem, wie viel Arbeit in der Konstrukteurs getan.

Es ist wahrscheinlicher, verwendet, weil die Semantik unterscheiden. Cloning bietet eine Möglichkeit, „Prototyp Semantik“ zu implementieren (wie in Javascript, selbst, etc.) in einer Sprache, die normalerweise nicht auf diese Weise neigt.

Wenn der Konstruktor Someobject tut teure Arbeit, wie etwas aus einer Datenbank greifen oder etwas Parsen, oder aus einer Datei etwas lesen, dann der Klon würde Sinn machen, um die Arbeit zu tun zu vermeiden.

Wenn der Konstruktor tut nichts dann gibt es wirklich keine Notwendigkeit Klon zu verwenden.

Edit: Code hinzugefügt, dass Klon zeigt nicht die gleiche Arbeit wie der Konstruktor zu tun hat:

class Main
    implements Cloneable
{
    private final double pi;

    public Main()
    {
        System.out.println("in Main");
        // compute pi to 1,000,000,000 decimal palaces
        pi = 3.14f;
    }

    public Object clone()
    {
        try
        {
            return (super.clone());
        }
        catch(final CloneNotSupportedException ex)
        {
            throw new Error(); // would not throw this in real code
        }
    }


    public String toString()
    {
        return (Double.toString(pi));
    }

    public static void main(String[] args)
    {
        final Main a;
        final Main b;

        a = new Main();
        b = (Main)a.clone();

        System.out.println("a = " + a);
        System.out.println("b = " + b);
    }
}

Der Haupt construtor wird einmal aufgerufen, wird die Rechen pi einmal durchgeführt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top