Domanda

Ho una classe generica che deve essere in grado di clonare oggetti del tipo di parametro. Un esempio molto semplice è sotto. Il compilatore rivendica clone () dall'oggetto tipo non è visibile.

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

Preferirei non far sì che il chiamante faccia la clonazione poiché ci sono altre cose che devono accadere per mantenere l'integrità dell'oggetto. Il codice sopra è solo un'illustrazione del problema senza il rumore degli altri dati che devo mantenere relativo all'oggetto clonato.

C'è un modo per aggirare questo o è un altro di quei casi in cui i progettisti di Java considerano razionalizzare le sue carenze l'equivalente di non averne nessuno?

È stato utile?

Soluzione

Un errore da parte di Java. La riflessione è la strada giusta per andare

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

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

Altri suggerimenti

Perché il metodo è contrassegnato come protected sul Object Classe, non puoi in generale chiamare questo metodo su oggetti arbitrari. Personalmente non pensavo che questo sarebbe stato un problema all'inizio (ehi, sono una sottoclasse di Object, quindi dovrei essere in grado di chiamare i suoi metodi protetti, giusto?), Ma il compilatore deve sapere che sei una sottoclasse del Oggetto targetLa classe (o nel suo pacchetto) per chiamare metodi protetti, nessuno dei quali si applica qui.

L'idea alla base del clone() il metodo è che le classi che lo supportano avrebbero sovrascritto il metodo, dichiarandolo come public.

L'unica vera soluzione qui che preserva la piena funzionalità è quella di utilizzare la riflessione per accedere al metodo e aggirare i modificatori di accesso. Un'alternativa sarebbe scrivere il tuo MyCloneable interfaccia che ha a pubblico clone() metodo dichiarato su di esso; Questo potrebbe funzionare se solo superate le tue lezioni di dominio, ma significa che non potresti usarlo su classi esterne (come java.util.String o java.util.ArrayList) dal momento che non puoi costringerli ad implementare la tua interfaccia.

Secondo le risposte al Domanda collegata, questo è un design molto dubbio.

Avevo bisogno di clonare un pojo con campi. Ciò che ha funzionato era il seguente:

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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top