[JAVA] Duplizieren Sie ein Objekt mit einem generischen Typ

Einführung

Eine Möglichkeit, nicht identische Objekte zu duplizieren, besteht darin, eine klonbare Schnittstelle zu implementieren, um "Object # clone" zu überschreiben.

Als ich jedoch ein Objekt mit dem generischen Typ wie im folgenden Code duplizieren wollte, war ich frustriert, weil ich nicht direkt auf "Object # clone" zugreifen konnte, sodass ich das Objekt auch dann duplizieren kann, wenn ich den generischen Typ verwende. Ich beschloss, verschiedene Dinge wie [^ best] zu entwickeln.

python


class GenericsSample {
    @SuppressWarnings("unchecked")
	static <T> T cloneSample(T obj) {
        return (T) obj.clone(); //Kompilierungsfehler (unsichtbare Klonmethode)
    }
}

Vorstellung der Schnittstelle

python


public interface CloneablePublicly<T> {
    T clone();
}

Anstelle von "Object # clone" habe ich eine Schnittstelle erstellt, um eine Methode zum Klonen von außen aufzurufen. Implementieren wir dies für die Klasse des Objekts, das den generischen Typ verwendet.

Implementierungsbeispiel


class Sample implements Cloneable, CloneablePublicly<Sample> {
    int value;
    public Sample(int value) {
        this.value = value;
    }
    @Override public Sample clone() {
        try {
            return (Sample) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }
}

Gleichzeitig wird natürlich auch die klonbare Schnittstelle implementiert. Wenn dies nicht implementiert ist, wird eine "CloneNotSupportedException" ausgelöst.

Objekt duplizieren

Wenn Sie anschließend die Methode wie folgt ändern, können Sie das Objekt anschließend mit dem generischen Typ duplizieren.

python


class GenericsSample {
    @SuppressWarnings("unchecked")
    static <T> T cloneSample(T obj) {
        if (obj instanceof Cloneable && obj instanceof CloneablePublicly) {
            return ((CloneablePublicly<T>) obj).clone();
        }
		return null;
    }
}

Anwendungsbeispiel


Sample samp1 = new Sample(1);
Sample samp2 = GenericsSample.cloneSample(samp1);
System.out.println(samp1.value);    // 1
System.out.println(samp2.value);    // 1
System.out.println(samp1 == samp2); //false (Duplikat nicht identischer Objekte)

Bonus

Wenn Sie nicht null zurückgeben möchten, geben Sie die optionalen [^ cost] wie folgt zurück: Auf diese Weise können Sie auch nichts tun, wenn Sie das Objekt nicht duplizieren können.

python


class GenericsSample {
    @SuppressWarnings("unchecked")
    static <T> Optional<T> cloneSample(T obj) {
        return Optional.ofNullable(obj)
            .filter(Cloneable.class::isInstance)
            .filter(CloneablePublicly.class::isInstance)
            .map(o -> ((CloneablePublicly<T>) obj).clone());
    }
}

Anwendungsbeispiel


Sample samp1 = new Sample(1);
GenericsSample.cloneSample(samp1).ifPresent(samp2 -> {
    System.out.println(samp1.value);    // 1
    System.out.println(samp2.value);    // 1
    System.out.println(samp1 == samp2); //false (Duplikat nicht identischer Objekte)
});

// Sample samp1 = null;Zu diesem Zeitpunkt nichts tun.

Nachtrag

Aus dem Kommentar von @ saka1029 haben wir die Vererbung und Implementierung der Schnittstelle mithilfe von Grenztypparametern eingeführt. Vielen Dank!

Vererbung der klonbaren Schnittstelle


interface CloneablePublicly<T> extends Cloneable {
    T clone();
}

Auf diese Weise müssen Sie die klonbare Schnittstelle nicht für Objektklassen implementieren, die generische Typen verwenden. ~~ Ich habe die Vererbungsfunktion der Schnittstelle komplett vergessen. ~~

Implementierungsbeispiel


class Sample implements CloneablePublicly<Sample> {
    ... //das Gleiche
}

python


class GenericsSample {
    static <T extends CloneablePublicly<T>> T cloneSample(T obj) {
        return Objects.isNull(obj) ? null : obj.clone();
    }
}

Grenzwertparameter werden verwendet, um die Typensicherheit zu gewährleisten, sodass keine manuelle Gussinspektion erforderlich ist. Die optionale Zeile wurde abgeschlossen.

python


class GenericsSample {
    static <T extends CloneablePublicly<T>> Optional<T> cloneSample(T obj) {
        return Optional.ofNullable(obj).map(CloneablePublicly::clone);
    }
}

[^ best]: Ich habe viel gesucht, aber ich konnte kein Material finden, das gut aussah, also habe ich es selbst gemacht. Wir entschuldigen uns für etwaige Unannehmlichkeiten, würden uns jedoch freuen, wenn Sie uns die Best-Practice-Methode oder Vorschläge beibringen könnten. [^ Kosten]: Laut "Effective Java 3rd Edition" ist die häufige Verwendung von Optional kostspielig. Wenn Sie sich Gedanken über die Leistung machen, ist es möglicherweise besser, darauf zu verzichten.

Recommended Posts

Duplizieren Sie ein Objekt mit einem generischen Typ
Schreiben Sie einen Nullfall mit dem Typ Optional, ohne die if-Anweisung zu verwenden
java: Wie schreibe ich eine generische Typliste? [Hinweis]
Ein Memorandum zum Erstellen eines erweiterten Loggers mit org.slf4j.Logger
Ich möchte eine generische Anmerkung für einen Typ erstellen
Zeichnen Sie mit PDFBox eine Linie in ein vorhandenes PDF-Dokument
Verfahren zum Veröffentlichen einer Anwendung mit AWS (4) Erstellen einer Datenbank