Question

Je cherchais des tutoriels expliquant sur Java Cloneable, mais n'a pas obtenu de bons liens, et le débordement de pile devient de plus en plus le choix évident de toute façon.

Je voudrais savoir ce qui suit:

  1. Cloneable signifie que nous pouvons avoir un clone ou une copie d'objets, par la mise en œuvre de l'interface Cloneable. Quels sont les avantages et inconvénients de le faire?
  2. Comment le clonage récursive se produire si l'objet est un objet composite?
Était-ce utile?

La solution

La première chose que vous devez savoir sur Cloneable est -. Ne l'utilisez pas

Il est très difficile à mettre en œuvre le clonage avec droit de Cloneable, et l'effort ne vaut pas.

Au lieu de cette utilisation d'autres options, comme apache-commons SerializationUtils (deep-clone) ou BeanUtils (peu profonde clone), ou simplement utiliser un constructeur de copie.

Voir pour les vues de Josh Bloch sur le clonage avec Cloneable, ce qui explique la de nombreux inconvénients de l'approche. ( Joshua Bloch était un employé de Sun, et a dirigé le développement de nombreuses fonctionnalités Java.)

Autres conseils

Cloneable lui-même est malheureusement juste un marqueur-interface, qui est:. Elle ne définit pas la méthode clone ()

Qu'est-ce que le fait, est de modifier le comportement de la méthode Object.clone () protégée, qui jette un CloneNotSupportedException pour les classes qui ne mettent pas en œuvre Cloneable et effectuer une copie peu profonde sage membre pour les classes qui le font.

Même si cela est le comportement que vous recherchez, vous aurez toujours besoin de mettre en œuvre votre propre méthode clone () afin de le rendre public.

Lors de la mise en œuvre de votre propre clone (), l'idée est de commencer avec l'objet de créer super.clone (), qui est garanti de la classe correcte, puis effectuez une population supplémentaire de champs dans le cas d'une copie peu profonde est pas ce que vous voulez. Appeler un constructeur de clone () serait problématique car cela briserait l'héritage dans le cas où une sous-classe veut ajouter sa propre logique cloneable supplémentaire; si elle devait appel super.clone (), il obtiendrait un objet de la mauvaise classe dans ce cas.

Cette approche évite toute logique qui peut être défini dans vos constructeurs bien, ce qui pourrait être problématique.

Un autre problème est que toutes les sous-classes qui oublient de passer outre clone () héritera la copie de faible profondeur par défaut automatiquement, ce qui est probablement pas ce que vous voulez en cas d'état mutable (qui va maintenant être partagé entre la source et la copie).

La plupart des développeurs ne pas utiliser Cloneable pour ces raisons, et mettre en œuvre simplement un constructeur de copie à la place.

Pour plus d'informations et les pièges potentiels de Cloneable, je recommande fortement le livre Effective Java par Joshua Bloch

  1. Clonage invoque une manière extra-linguistique de la construction d'objets - sans constructeur.
  2. Le clonage vous oblige à traiter avec une certaine façon CloneNotSupportedException -. Ou déranger code client pour traiter
  3. Avantages sont petites - vous n'avez tout simplement pas écrire manuellement un constructeur copie
  4. .

Alors, utilisez judicieusement Cloneable. Il ne vous donne pas suffisamment d'avantages par rapport à l'effort que vous devez appliquer à tout droit.

Le clonage est un paradigme de programmation de base. Le fait que Java a peut-être mis en œuvre, il mal à bien des égards ne pas du tout besoin de diminuer le clonage. Et, il est facile de mettre en œuvre le clonage qui cependant vous voulez travailler pour travailler, peu profond, profond, mélangé, peu importe. Vous pouvez même utiliser le clone de nom pour la fonction et non mettre en œuvre Cloneable si vous aimez.

Supposons que j'ai des classes A, B et C, B et C sont dérivées de A. Si j'ai une liste d'objets de type A comme ceci:

ArrayList<A> list1;

Maintenant, cette liste peut contenir des objets de type A, B ou C. Vous ne savez pas quel type les objets sont. Donc, vous ne pouvez pas copier la liste comme ceci:

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    list2.add(new A(a));
}

Si l'objet est en fait de type B ou C, vous ne serez pas la copie à droite. Et, si A est abstraite? Maintenant, certaines personnes ont suggéré ceci:

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    if(a instanceof A) {
        list2.add(new A(a));
    } else if(a instanceof B) {
        list2.add(new B(a));
    } else if(a instanceof C) {
        list2.add(new C(a));
    }
}

Ceci est une idée très, très mauvais. Que faire si vous ajoutez un nouveau type dérivé? Et si B ou C sont dans un autre paquet et vous n'avez pas accès à eux dans cette classe?

Qu'est-ce que vous voulez faire est la suivante:

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    list2.add(a.clone());
}

Beaucoup de gens ont indiqué pourquoi l'implémentation Java de base du clone est problématique. Mais, il est facile à surmonter cette façon:

Dans la classe A:

public A clone() {
    return new A(this);
}

Dans la classe B:

@Override
public B clone() {
    return new B(this);
}

Dans la classe C:

@Override
public C clone() {
    return new C(this):
}

Je ne suis pas mise en œuvre Cloneable, tout en utilisant le même nom de fonction. Si vous ne le faites pas comme ça, nommez autre chose.

A) Il n'y a pas beaucoup d'avantages du clone sur un constructeur de copie. Probablement la plus grande est la possibilité de créer un nouvel objet du même type de dynamique exacte (en supposant que le type déclaré est clonable et a une méthode clone public).

B) Le clone par défaut crée une copie peu profonde, et il restera une copie peu profonde à moins que votre mise en œuvre du clone change qui. Cela peut être difficile, surtout si votre classe a des champs finaux

Bozho est juste, clone peut être difficile d'obtenir le droit. Un constructeur / usine copie servira la plupart des besoins.

Quels sont les inconvénients de Cloneable?

Le clonage est très dangereux si l'objet que vous copiez a composition.You besoin de penser ci-dessous effet secondaire possible dans ce cas parce que clone crée copie superficielle:

Disons que vous avez un objet à gérer db manipulation connexes. Par exemple, cet objet a comme objet une Connection de la propriété.

Alors, quand quelqu'un crée clone de originalObject, l'objet créé, disons, cloneObject. Ici, le originalObject et cloneObject détiennent la même référence pour objet Connection.

Disons que originalObject ferme l'objet Connection, maintenant le cloneObject ne fonctionnera pas parce que l'objet connection a été partagé entre eux et il a été fermé par le actaually originalObject.

problème similaire peut se produire si vous laissez dire à cloner un objet qui a iostream comme une propriété.

Comment le clonage récursive se produire si l'objet est un objet composite?

Cloneable effectue une copie peu profonde. La signification est que les données de l'objet et de l'objet clone d'origine pointeront à la même référence / mémoire. contraire dans le cas de copie en profondeur, les données de la mémoire de l'objet d'origine est copié dans la mémoire de l'objet clone.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top