Небезопасные или непроверенные выражения Java: клонирование массива - PullRequest
1 голос
/ 18 января 2012

Я получил непроверенную ошибку выражения при компиляции и обнаружил, что ошибочная строка равна

ArrayList<Integer> items = (ArrayList<Integer>) this.items.clone();

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

  • Я мог бы использовать @SuppressWarnings("unchecked"), но это просто скрывает проблему (хотя я не ожидаю ничего)
  • Если я клонирую вручную, просматривая все элементыЯ думаю, что это будет медленнее

Какой правильный способ сделать это?

Ответы [ 6 ]

4 голосов
/ 18 января 2012

Если ваши элементы являются целыми числами, выполнение «глубокого копирования» на самом деле не является проблемой, поскольку нет причин, по которым вам нужно было бы копировать объект Integer.Просто используйте new ArrayList<Integer>(this.items).

Но для справки ни clone (), ни конструктор копирования ArrayList не будут делать глубокое копирование.Только потому, что ваши типы элементов не нуждаются в глубоком копировании, это удовлетворяет ваши потребности.

1 голос
/ 18 января 2012

Целые числа неизменны, поэтому не имеет значения, делаете ли вы глубокую копию или нет.

используйте служебный класс Collections в java.util:

import java.util.Collections;
...
ArrayList<Integer> items = new ArrayList<Integer>(this.items.size());
Collections.copy(items, this.items);
1 голос
/ 18 января 2012

Вы можете получить то же поведение с new ArrayList<Integer>(this.items).В любом случае это копия мелкая .

API

0 голосов
/ 18 января 2012

Как уже отмечали другие, клонирование ArrayList не клонирует его элементы. Если вы хотите сделать глубокую копию содержимого, есть хитрый трюк: сериализация и десериализация массива. (Это работает, потому что ArrayList и Integer оба реализуют Serializable.) Однако это не избавляет от необходимости подавлять предупреждения о непроверенной конверсии.

// Write the object out to a byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(this.items);
byte[] bytes = bos.toByteArray();

// Retrieve an input stream from the byte array and read
// a copy of the object back in.
ObjectInputStream in = new ObjectInputStream(
    new ByteArrayInputStream(bytes));
ArrayList<Integer> items = (ArrayList<Integer>) in.readObject();

Если весь ваш объект может быть объявлен как Serializable, вы можете использовать его вместо операции клонирования для создания глубокой копии. Также см. в этой статье , чтобы узнать, как избежать затрат на копирование байтов из ByteArrayOutputStream.

.
0 голосов
/ 18 января 2012

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

0 голосов
/ 18 января 2012

Из-за обратной совместимости, требуемой при введении обобщений в Java API, в некоторых ситуациях невозможно использовать приведение типов и @SuppressWarnings("unchecked").

Кроме того, см. здесь , чтобы узнать, почему clone() следует использовать с осторожностью: делает мелкое копирование, что хорошо для приматов, но опасно для объектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...