Une façon de dupliquer des objets non identiques est d'implémenter l'interface clonable et de remplacer ʻObject # clone`.
Cependant, lorsque je voulais dupliquer un objet en utilisant le type générique comme dans le code suivant, j'étais frustré car je ne pouvais pas accéder directement à ʻObject # clone`, donc je peux dupliquer l'objet même si j'utilise le type générique. J'ai décidé de concevoir diverses choses comme [^ best].
python
class GenericsSample {
@SuppressWarnings("unchecked")
static <T> T cloneSample(T obj) {
return (T) obj.clone(); //Erreur de compilation (méthode de clonage invisible)
}
}
python
public interface CloneablePublicly<T> {
T clone();
}
Au lieu de ʻObject # clone`, j'ai créé une interface pour appeler une méthode de clonage de l'extérieur. Implémentons ceci pour une classe d'objets qui utilisent des types génériques.
Exemple d'implémentation
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);
}
}
}
Bien entendu, l'interface clonable est également implémentée en même temps. Si cela n'est pas implémenté, il lèvera une CloneNotSupportedException
.
Après cela, si vous modifiez la méthode comme suit, par exemple, vous pouvez dupliquer l'objet à l'aide du type générique.
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;
}
}
Exemple d'utilisation
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 (duplication d'objets non identiques)
Si vous ne souhaitez pas retourner null, renvoyez le [^ cost] facultatif comme suit: Cela vous permet également de ne rien faire si vous ne pouvez pas dupliquer l'objet.
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());
}
}
Exemple d'utilisation
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 (duplication d'objets non identiques)
});
// Sample samp1 = null;À ce moment-là, ne faites rien.
À partir du commentaire de @ saka1029, nous avons introduit l'héritage et l'implémentation d'interface en utilisant des paramètres de type de frontière. Je vous remercie!
Héritage de l'interface clonable
interface CloneablePublicly<T> extends Cloneable {
T clone();
}
De cette façon, vous n'avez pas à vous soucier d'implémenter l'interface clonable pour les classes d'objets qui utilisent des types génériques. ~~ J'ai complètement oublié la fonction d'héritage de l'interface. ~~
Exemple d'implémentation
class Sample implements CloneablePublicly<Sample> {
... //le même
}
python
class GenericsSample {
static <T extends CloneablePublicly<T>> T cloneSample(T obj) {
return Objects.isNull(obj) ? null : obj.clone();
}
}
Les paramètres limites sont utilisés pour assurer la sécurité du type, éliminant le besoin d'une inspection manuelle de la fonte. La ligne facultative est terminée.
python
class GenericsSample {
static <T extends CloneablePublicly<T>> Optional<T> cloneSample(T obj) {
return Optional.ofNullable(obj).map(CloneablePublicly::clone);
}
}
[^ best]: J'ai beaucoup cherché, mais je n'ai trouvé aucun matériel qui avait l'air bien, alors je l'ai fait moi-même. Nous vous prions de nous excuser pour tout inconvénient, mais nous vous serions reconnaissants de bien vouloir nous enseigner la méthode ou les suggestions des meilleures pratiques. [^ Coût]: Selon "Effective Java 3rd Edition", il est coûteux d'utiliser fréquemment Optionnel, il peut donc être préférable de ne pas l'utiliser si vous êtes préoccupé par les performances.
Recommended Posts