Java Deep Clone - клонировать каждый элемент в ArrayList, если Cloneable, независимо от типа

1

У меня есть ArrayList a, который может содержать объекты любого типа. Затем мне нужно перебрать элементы массива ArrayList. Если элемент реализует Cloneable, мне нужно клонировать элемент (что означает сделать его копию и присвоить ему свое место в памяти) и добавить клонированный элемент в ArrayList b. Проблема заключается в кастинге. Мне нужно указать правильный тип объекта, а затем вызвать clone(). (Потому что clone() в объекте защищен.)

В приведенном ниже коде мне удалось сделать это с помощью нескольких операторов if. На каждом элементе я говорю, если Cloneable, а затем вложен в этот оператор if, у меня есть другие операторы if, проверяющие, например, правильный тип. Когда программа находит нужный тип, она бросает и клонирует. Весь этот код работает, но я хотел бы использовать метод cast и then clone() без этих операторов if, поскольку могут быть классы, о которых я еще не знаю. Есть ли способ сделать это? (Я могу использовать класс Class.cast(), но у меня не было успеха при вызове clone() для таких приведений.)

Я попытался сериализовать список массивов, реализовать свой собственный интерфейс (с помощью метода clone()) и вызвать конструктор копирования. Ни одно из них не работает для каждого случая. Близко, как я могу судить, кастинг, а затем клонирование - единственный верный способ заставить его работать. Если есть способ бросить и клонировать без указания точного класса, это будет работать для каждого случая. В противном случае я в тупик и нуждаюсь в другом решении. (Если есть способ перебрать все поля в объекте независимо от доступности, это тоже может работать.)

Вот мой код:

// Establish variables
TestClass t = new TestClass();
TestClass u = new TestClass(1);
Point p = new Point();
Point q = new Point(1, 2);

// Set up ArrayList a
ArrayList a = new ArrayList();
a.add(t);
a.add(u);
a.add(p);
a.add(q);

// Get number of elements in a
int n = a.size();

// Set up ArrayList b
ArrayList b = new ArrayList();

// Clone all Cloneable elements from a into b
for (int i = 0; i < n; i++)
    if (a.get(i) instanceof Cloneable)
        if (a.get(i) instanceof TestClass)
            b.add(((TestClass)a.get(i)).clone());
        else if (a.get(i) instanceof Point)
            b.add(((Point)a.get(i)).clone());
    //ISSUE: I need to be able to cast and then clone based on the class a.get(i) represents, to avoid these if statements.

// Change initial variables. They change in ArrayList a (due to referencing the same memory) but not b
t.i = 2;
u.i = 3;
p.x = 3;
p.y = 4;
q.x = 5;
q.y = 6;

System.out.println(a);
System.out.println(b);

TestClass и Point - это классы, которые я написал. Они реализуют Cloneable.

Спасибо за любую помощь, которая предоставляется.

Теги:
arraylist
casting
clone

2 ответа

1

Весь механизм клонирования в Java в основном нарушен. См. Например, http://www.artima.com/intv/issues3.html.

Вы можете использовать библиотеку, которая имеет все функции на месте (http://code.google.com/p/cloning/ - (рекомендации по использованию утилиты Deep clone для Cojones) или создать собственный интерфейс, например

public interface Copyable<T> {
 T copy();
}

Пусть все классы, которые вам нужны, реализуют этот интерфейс. Если вы знаете, какой класс он есть, вы можете просто использовать его как

SomeClass a = new SomeClass();
SomeClass clone = a.copy();

Или, если вы только знаете, что это копируемый:

Copyable<?> copy = x.copy();

Но в большинстве случаев лучше использовать существующее решение, подобное вышеизложенному.

(Edit: всегда лучший выбор не использовать javas-собственный клон-материал :))

  • 1
    Я посмотрю в библиотеки, как только смогу. Спасибо!
1

Я думаю, вы можете сделать это, используя отражение,

if (a.get(i) instanceof Cloneable) {
  Cloneable c = (Cloneable) a.get(i);
  try {
    Method cloneMethod = c.getClass().getMethod("clone", new Class<?>[] {});
    cloneMethod.setAccessible(true);
    Object clone = cloneMethod.invoke(c, new Object[] {});
    b.add(clone);
  } catch (Exception e) {
    // Add real error handling.
    e.printStackTrace();
  }
} else {
  // It isn't cloneable.
}
  • 0
    Извините, но это не работает. Я получаю следующую ошибку: не могу найти символ символа: метод clone () расположение: interface java.lang.Cloneable b.add (c.clone ()); Возможно, потому что clone () находится в Object, а не в Cloneable? (Клонируемый пустой)
  • 0
    Каждый Cloneable также имеет тип Object, и версия Object клона также не видна.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню