Supposons que vous ayez une référence de type Je voulais mettre en œuvre une méthode générique qui filtrera tout type de collecte donnée. Par conséquent, la méthode prendra java.util.collection code> dans une méthode et ne peut pas dire quelle implémentation de java.util.collection code> sera-t-il pointant à l'exécution temps, est-il possible de cloner la collection? p>
java.util.collection code> comme entrée. Cependant, au-delà de cela, je ne voulais pas modifier la collection d'origine, alors je voulais cloner la collection. P>
7 Réponses :
En théorie, il est possible de réflexion, mais pas tous les Ce que je ferais à la place, c'est simplement vérifier les interfaces de la collection d'entrée et renvoyer une implémentation "par défaut" pour ce type. Donc, par exemple: p> ans ainsi de suite. P> p> la collection code> peuvent (ou doivent) être instanciés de cette façon. Un premier exemple est le résultat de collections.singletonlist () code>, qui n'a pas de constructeurs publics du tout. D'autres collections spéciales peuvent également soulever d'autres problèmes.
Demain, tout le monde peut implémenter la collection.
Si la collection implémente clonable code>, vous pouvez le faire. Vous n'auriez pas à vous soucier du type exact; Clone de la collection () CODE> La mise en œuvre prendrait en charge cela. P>
Objet.clone () est protégé. Vous ne pouvez pas simplement l'appeler si vous ne connaissez pas le type réel de l'objet. Eh bien, vous pouvez peut-être le faire en utilisant la réflexion comme Biziclop suggéré dans sa réponse.
Correction de ce problème - oublié que vous avez besoin de mettre en œuvre clonable code> et de remplacement clone () code>.
Même si vous implémentez clonable code>, la méthode du clone peut ne pas être publique, voir le Javadoc download.oracle.com/javase/6/docs/aplon/java/lang/cloneable.ht ml
Oui, voir la réponse de @ Ralph pour la solution à cela. (Je pense)
Je vois trois options: p>
Demandez à l'appelant de fournir une collection vide pour copier les éléments cibles entre la source et la destination. p> li>
Définissez une interface d'usine pour créer une collection vide et demander à l'appelant de fournir une implémentation d'usine. Ensuite, copiez les éléments cibles entre la source et la destination. P> li>
ol> s'appuyer sur la méthode de la collection CLONE CODE> (en supposant que cela implémente clonable code>) puis retirez les éléments indésirables. Strike> Edit: em> comme indiqué dans les commentaires et autres réponses, Clone () Code> n'est pas public et n'est donc pas accessible. P> li>
Consultez mon commentaire sur Michael Post sur la méthode du clone et l'interface CloneBL.
Malheureusement, la collection d'interface ne dit rien sur la mise en œuvre d'une interface clignaire.
mais ce que vous pouvez toujours faire est de copier la collection: p> Si vous voulez seulement vous assurer qu'il n'est pas modifié, enveloppez-la avec une collection non modifiable au lieu de le cloner: P> Collection<T> unmodifiable = Collections.unmodifiableCollection(original);
Fortez quelques-unes des implémentations de Collection CODE> DO, SO L'instanceOf code> fonctionnerait pour de nombreux cas.
Regardez le commentaire sur d'autres réponses: Clonable ne signifie pas que vous pouvez utiliser la méthode du clone.
La référence à la collection non modifiable restera locale, la collection d'origine est toujours modifiable par des références à l'extérieur, je voulais modifier une copie de la collection d'origine et le renvoyer.
@Nicloas: ma faute - j'ai enlevé cette partie de la réponse
Je vais démontrer à Scala, car il a une replace où je peux tester, mais la même sémantique devrait travailler dans Java. Le Scala Replucle me dit que TheClone a type statique type MAINTENANT, je suppose que ce que vous voulez est une méthode qui renvoie un type statique En Java, je pense que c'est p> objet code> (vous pouvez lancer ceci sur collection [int] code> ou linkedlist [int] code>), mais le type dynamique du clone est toujours LinkedList CODE>. P> linkedlist code> quand il reçoit un type statique LinkedList Code> et renvoie un type statique ArrayList Code> Lorsqu'il reçoit un type statique ArrayList code>, etc., auquel cas p>
Mieux vaut filtrer la collection en la modifiant dans votre méthode. Jusqu'à l'appelant pour vous fournir la collection d'origine ou une copie appropriée de celle-ci. P>
Si vous vraiment, vraiment, vraiment, vraiment besoin de le faire, il y a un piratage laid.
public static <T> T tryToClone(T object)
throws CloneNotSupportedException {
Object clone = null;
// Use reflection, because there is no other way
try {
Method method = object.getClass().getMethod("clone");
clone = method.invoke(object);
} catch (InvocationTargetException e) {
rethrow(e.getCause());
} catch (Exception cause) {
rethrow(cause);
}
if (object.getClass().isInstance(clone)) {
@SuppressWarnings("unchecked") // clone class <= object class <= T
T t = (T) clone;
return t;
} else {
throw new ClassCastException(clone.getClass().getName());
}
}
private static void rethrow(Throwable cause)
throws CloneNotSupportedException {
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
if (cause instanceof Error) {
throw (Error) cause;
}
if (cause instanceof CloneNotSupportedException) {
throw (CloneNotSupportedException) cause;
}
CloneNotSupportedException e = new CloneNotSupportedException();
e.initCause(cause);
throw e;
}
FYI, cela vient d'ici: code.google.com/p/google-Collections/source/trunt/trunk/src / ... - Nous l'avons ensuite supprimé, car c'est un terrible no -Good inutile sale hacky hacky hacky.
Pourquoi avez-vous besoin de votre collection de sortie pour être le même type que l'entrée?
La collection d'origine devrait-elle rester non modifiée?
@Nicolas: matière de commodité :)