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)
}
}
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.
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)
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.
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