2010-02-20 6 views
3

Qu'est-ce qu'un moyen rapide et facile de remplir un tableau Java avec des clones d'un seul objet?Remplir un tableau avec des clones d'un seul objet

par exemple. après:

Rectangle[] rectangles = new Rectangle[N]; 
fillWithClones(rectangles, new Rectangle(1, 2, 3, 4)); 

la matrice rectangles contiendrait N instances distinctes, Rectangle initialisés avec les mêmes coordonnées.

Je suis conscient des défauts de Object.clone() en Java, mais dans ce cas je sais que les objets à copier ont non lanceuse, clone() publics méthodes, mais ils peuvent ou ne peuvent pas avoir un constructeur de copie publique.

Je suppose qu'il existe une méthode de bibliothèque quelque part, mais je ne pense pas que ce soit dans le JDK, Commons-collections ou Guava.

Répondre

2

Si vous ne disposez pas du type spécifique que vous voulez travailler avec au moment de la compilation, vous devrez appeler la méthode clone par réflexion.

private static <T> T cloneByReflection(T object) { 
    try { 
     return (T) object.getClass().getMethod("clone").invoke(object); 
    } catch (Exception e) { 
     return null; // or whatever you want to do 
    } 
} 

public static <T> void fillWithClones(T[] array, T template) { 
    for (int i = 0; i < array.length; ++i) 
     array[i] = cloneByReflection(template); 
} 
+0

La signature de la deuxième méthode doit être simplifiée à public static void fillWithClones (Object [] tableau, Object template) ' – user102008

0

Pour les rectangles:

public void fillWithClones(Rectangle[] arr, Rectangle src) { 
    for(int xa=0,len=arr.length; xa<len; xa++) { arr[xa]=(Rectangle)src.clone(); } 
    } 
+0

Pour les types inconnus, 'Object.clone' est protégé. Vous ne pouvez accéder à cette méthode que par réflexion (et seulement si le type de cible définit un override public, bien sûr). –

+0

@Chris: Merde, ce qu'est un clonable. J'ai supprimé la méthode incorrecte non typée. –

0

@Chris Jester-Young vous donne une recette pour faire ce que vous voulez faire.

Mais je dirais qu'il y a quelque chose qui ne va pas dans une application qui fait ce genre de chose.

  • Pourquoi votre demande besoin de faire des copies profondes de tableaux de choses au hasard? Si vous ne connaissez pas les types de choses, comment savez-vous que la copie est nécessaire?

  • Que doit faire votre application lorsque la matrice contient un objet non clonable? Jetez-vous une exception? Est-ce que vous mettez un null dans le tableau, exigeant plus tard une vérification nulle?

Il est une meilleure conception d'avoir tous les objets que vous souhaitez cloner implémenter une interface avec une méthode de méthode (public) clone. De cette façon, vous pouvez avoir une solution statiquement typée (pas d'exception de type dynamique!) Et vous pouvez éviter les frais généraux d'appeler clone de manière réfléchie.

+0

Les types ne sont pas" random ".Le type est connu dans chaque cas, mais je préférerais une méthode générique pour garder le programme plus petit. Certaines classes proviennent du JDK, donc je ne peux pas définir une nouvelle interface pour eux. Si cette méthode rencontre un objet non clonable, elle devrait lancer une exception CloneNotSupportedException. – finnw

+0

@finnw - qu'en est-il de la première balle? Pourquoi votre application a-t-elle besoin de cloner des objets en premier lieu? –

0

Si un constructeur de copie pourrait existe (et que vous voulez l'utiliser si elle le fait), vous pouvez faire quelque chose comme ceci:

(Edit: code mis à jour pour utiliser un tableau au lieu de la liste):

private static <T> void fillWithClones(T[] array, T object) 
{ 
    try 
    { 
    @SuppressWarnings("unchecked") 
    Class<T> clazz = (Class<T>)object.getClass(); 
    Constructor<T> c = clazz.getConstructor(object.getClass()); 

    try 
    { 
     for (int i = 0; i < array.length; i++) 
     { 
     array[i] = (T)c.newInstance(object); 
     } 
    } 
    catch (Exception e) 
    { 
     // Handle exception or rethrow... 
    } 
    } 
    catch (NoSuchMethodException e) 
    { 
    // No copy constructor, try clone option... 
    } 
} 

Une partie de la gestion des exceptions pourraient être tondu, bien sûr.

+0

Un constructeur 'T (T)' n'est pas nécessairement un constructeur de copie (par exemple 'JFrame',' JScrollPane', 'ClassLoader',' Properties', 'Throwable'.) – finnw

+0

@finnw: Oui, un bon ramassage. Je suppose qu'à la fin de la journée, vous devez savoir quelque chose sur les objets que vous dupliquez pour choisir une solution appropriée. – Ash

+0

Les génériques n'ont aucun effet ici. Faites juste 'private void fillWithClones (Object [] array, Objet Object)' et changez le 'T' en'? ' – user102008