2013-04-03 2 views
0

У меня есть следующее.Копировать объект любого типа

public static <T> T someMethod(T originalObject) { 

    T modifiedObject = /* copy of original object (HOW DO YOU DO THIS?) */ 

    /* Some logic that modifies the object. */ 
    ... 

    return modifiedObject; // without changing original Object 

} 

Вопрос в том, как создать копию типа T, если вы не знаете, какой тип T может быть?

REVISION - чтобы быть более ясным, я просто вставлю свой код.

public class ObjectMerger { 

    public static <T> T merge(T original, T patch) throws IllegalArgumentException, IllegalAccessException { 

     Object mergedObject = original // TODO: implement a way to copy original 

     Field[] inheritedFields = patch.getClass().getFields(); 
     Field[] memberFields = patch.getClass().getDeclaredFields(); 
     Field[] allFields = (Field[]) ArrayUtils.addAll(inheritedFields, memberFields); 

     for (Field field : allFields) { 

      Boolean originalAccessibility = field.isAccessible(); 
      field.setAccessible(true); 

      Object fieldValue = field.get(patch); 

      if (fieldValue != null) { 

       Boolean fieldIsFinal = Modifier.isFinal(field.getModifiers()); 

       if (!fieldIsFinal) { 
        field.set(mergedObject, fieldValue); 
       } 

      } 

      field.setAccessible(originalAccessibility); 

     } 

     return mergedObject; 

    } 

} 

Примечание: Я попытался сказать, что T extends Cloneable и это не выход. Я считаю, что реализация Cloneable не гарантирует, что клон будет виден.

ПРИМЕЧАНИЕ: ПРИМЕЧАНИЕ DUPLICATE!

Для тех, кто отмечает это как дубликат, пожалуйста, прочитайте вопрос. Это запрашивает способ дублирования объекта неизвестного типа. В любом случае, из того, что я понял, это невозможно. Спасибо всем за ваш вклад.

+0

Вы пытаетесь клонировать объект? –

+0

Не могли бы вы объяснить, почему вы это делаете? Чтобы мы могли предложить вам правильный способ сделать это. –

+0

Я пересмотрел свой вопрос. Надеюсь, это станет немного более ясным. Благодарю. –

ответ

2

Если у вас нет абсолютно никакой информации о том, что такое T, то лучше всего проверить это, если оно реализует Cloneable и .clone().

if (originalObject implements Cloneable) { 
    T modifiedObject = originalObject.clone(); 
    // ... 
} else { 
    throw new IllegalArgumentException(); 
} 

Вы можете также ограничить T:

public static <T extends Cloneable> T someMethod(T originalObject) { 
    T modifiedObject = originalObject.clone(); 
} 

В любом случае, как вы рассчитывать на изменение объекта, который вы не имеете ни малейшего представления о том, что это такое? Ваш случай использования звучит немного странно. Может быть, вам будет легче помочь, если вы опишете, что вы пытаетесь сделать (а не как вы пытаетесь это сделать).

+0

Я пытался сделать это раньше и не повезло. Я не верю, что реализация Cloneable гарантирует, что метод clone будет виден, и компилятор, похоже, согласен. Вы бы подумали. То, что я пытаюсь сделать, - объединить два объекта любого типа, используя отражение, исследуя поля. На самом деле я создал метод, который делает это успешно, но я бы не хотел изменять оригинал. –

+0

Что вы подразумеваете под * merge two objects *? –

+0

О видимости 'Cloneable' и' .clone() ', вы правы. Вы могли бы попытаться называть это отражением, но это кажется очень ненадежным. Давайте посмотрим, что вы можете сказать о * объединить два объекта *, и, возможно, мы сможем найти хорошее решение. –

1

Тогда возникает вопрос, как к создать копию типа T, если вы понятия не имеете, какой тип T может быть?

Если вы действительно не знаете, что такое T, вы просто не можете сделать копию.

Во-первых, универсального API для копирования объектов не существует (любой данный тип может поддерживать или не поддерживать clone()).

Однако основная причина заключается в том, что T может вообще не поддерживать копирование. Например, что, если T - FileInputStream? Как вы собираетесь копировать экземпляр этого?

Кроме того, как вы собираетесь реализовать /* Some logic that modifies the object. */, если вы не знаете, что такое T?

+0

Правильно Я думаю, что вопрос непонятен –

0

Есть два варианта:

  • Используйте кнопки clone() и Cloneable, как уже было предложено в другом ответе
  • Если вы не хотите, чтобы ограничить к Cloneable затем использовать deep/shallow clone library, который использует отражение. (Не рекомендуется, но вариант). Следует следить за тем, чтобы объект поддерживал копирование.
1

Если вы готовы использовать XStream, вот решение,

XStream xstream = new XStream(); 

return (T) xstream.fromXML(XSTREAM.toXML(originalObject)); 
1

В названии говорит Копировать объект любого типа, то я думаю, что единственный вариант у вас есть, чтобы использовать Reflection API , Кроме того, даже если вы используете отражение, вам нужно иметь некоторые критерии в зависимости от того, что вы создаете копию, например, какие атрибуты вы хотите скопировать из исходного объекта и т. Д.

Смежные вопросы