[JAVA] Dupliquer un objet à l'aide d'un type générique

introduction

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

Présentation de l'interface

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.

Objet dupliqué

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)

prime

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.

Postscript

À 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

Dupliquer un objet à l'aide d'un type générique
Ecrire une casse nulle en utilisant le type facultatif sans utiliser l'instruction if
java: Comment écrire une liste de types génériques [Note]
Un mémorandum pour créer un enregistreur étendu à l'aide de org.slf4j.Logger
Je souhaite créer une annotation générique pour un type
Tracez une ligne sur un document PDF existant à l'aide de PDFBox
Procédure de publication d'une application à l'aide d'AWS (4) Création d'une base de données