Question

J'ai une classe générique qui a besoin de pouvoir cloner des objets de type paramètre.Un exemple très simple est ci-dessous.Le compilateur affirme que clone () du type Object n'est pas visible.

public class GenericTest<T extends Cloneable>
    {
    T obj;
    GenericTest(T t)
        {
        obj = t;
        }
    T getClone()
        {
        // "The method clone() from the type Object is not visible."
        return (T) obj.clone();
        }
    }

Je préférerais que l'appelant ne fasse pas le clonage car il y a d'autres choses qui doivent arriver pour maintenir l'intégrité de l'objet.Le code ci-dessus est juste une illustration du problème sans le bruit des autres données que je dois maintenir liées à l'objet cloné.

Y a-t-il un moyen de contourner ce problème ou s'agit-il d'un autre de ces cas où les concepteurs de Java considèrent rationaliser ses lacunes comme n'en avoir aucun?

Était-ce utile?

La solution

Une erreur de la part de Java.La réflexion est la bonne voie à suivre

static Method clone = Object.class.getMethod("clone"); 

static public <T extends Cloneable> 
T clone(T obj)
    return (T) clone.invoke(obj);

Autres conseils

Comme la méthode est marquée comme protected sur la classe Object, vous ne pouvez pas en général appeler cette méthode sur des objets arbitraires. Personnellement, je ne pensais pas que ce serait un problème au début (hé, je suis une sous-classe de Object, donc je devrais pouvoir appeler ses méthodes protégées, non?), Mais le compilateur doit savoir que vous êtes un sous-classe de la classe de l ' objet cible (ou dans son package) afin d'appeler des méthodes protégées, dont aucune ne s'applique ici.

L'idée derrière la méthode clone() est que les classes qui la supportaient remplaceraient la méthode, la déclarant comme public.

La seule vraie solution ici qui préserve toutes les fonctionnalités est d'utiliser la réflexion pour accéder à la méthode et contourner les modificateurs d'accès. Une alternative serait d'écrire votre propre interface MyCloneable qui a une méthode public clone() déclarée dessus; cela peut fonctionner si vous ne passez que vos propres classes de domaine, mais cela signifie que vous ne pouvez pas l'utiliser sur des classes externes (telles que java.util.String ou java.util.ArrayList) car vous ne pouvez pas les forcer à implémenter votre interface.

Selon les réponses à la question liée , c'est une conception très douteuse.

J'avais besoin de cloner un POJO avec des champs.Voici ce qui a fonctionné:

public static Object clone(Object o)
{
  Object clone = null;

  try
  {
     clone = o.getClass().newInstance();
  }
  catch (InstantiationException e)
  {
     e.printStackTrace();
  }
  catch (IllegalAccessException e)
  {
     e.printStackTrace();
  }

  // Walk up the superclass hierarchy
  for (Class obj = o.getClass();
    !obj.equals(Object.class);
    obj = obj.getSuperclass())
  {
    Field[] fields = obj.getDeclaredFields();
    for (int i = 0; i < fields.length; i++)
    {
      fields[i].setAccessible(true);
      try
      {
        // for each class/suerclass, copy all fields
        // from this object to the clone
        fields[i].set(clone, fields[i].get(o));
      }
      catch (IllegalArgumentException e){}
      catch (IllegalAccessException e){}
    }
  }
  return clone;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top