Многоразовый метод преобразования Iterable <T> в T []?
Я пытаюсь написать общий метод, чтобы вернуть содержимое формы Iterable в массиве.
Вот что у меня есть:
public class IterableHelp
{
public <T> T[] toArray(Iterable<T> elements)
{
ArrayList<T> arrayElements = new ArrayList<T>();
for(T element : elements)
{
arrayElements.add(element);
}
return (T[])arrayElements.toArray();
}
}
Но я получаю предупреждение о компиляторе 'Примечание:...\IterableHelp.java использует непроверенные или небезопасные операции.'
Любые мысли о другом подходе, которые позволили бы избежать такого предупреждения?
Ответы
Ответ 1
В Google Guava существует метод Iterables.toArray
.
Рассматривая источник, он определяется как:
/**
* Copies an iterable elements into an array.
*
* @param iterable the iterable to copy
* @param type the type of the elements
* @return a newly-allocated array into which all the elements of the iterable
* have been copied
*/
public static <T> T[] toArray(Iterable<? extends T> iterable, Class<T> type) {
Collection<? extends T> collection = toCollection(iterable);
T[] array = ObjectArrays.newArray(type, collection.size());
return collection.toArray(array);
}
Где ObjectArrays.newArray
в конечном итоге делегирует метод, который выглядит следующим образом:
/**
* Returns a new array of the given length with the specified component type.
*
* @param type the component type
* @param length the length of the new array
*/
@SuppressWarnings("unchecked")
static <T> T[] newArray(Class<T> type, int length) {
return (T[]) Array.newInstance(type, length);
}
Итак, похоже, что нет возможности полностью избежать @SuppressWarnings
, но вы можете и должны, по крайней мере, ограничить его до наименьшей возможной области.
Или, еще лучше, просто используйте чужую реализацию!
Ответ 2
Невозможно избавиться от предупреждения unchecked or unsafe operations
или создать массив TypeSafe без редактирования вашей сигнатуры метода.
Подробнее об этом расскажите отчет об ошибках.
Один из способов - передать в предварительно выделенный массив типа T
:
public class IterableHelp
{
public <T> T[] toArray(final T[] t, final Iterable<T> elements)
{
int i = 0;
for (final T element : elements)
{
t[i] = element;
}
return t;
}
}
Это избавляет от предупреждения unchecked or unsafe
, но также помещает onus в вызывающий класс для создания массива с правильными границами, чтобы начать с того, какие виды поражений предназначены для вашего метода удобства.
Если вы хотите динамически создавать массив TypeSafe, вы действительно не можете сделать это в способе TypeSafe в Java.
Это работает и компилируется, но не решает проблему неконтролируемой или небезопасной, она просто перемещает ее в другое место. Мне пришлось добавить аннотацию @SuppressWarnings
, чтобы заставить ее перестать жаловаться на актерский состав.
@SuppressWarnings({"unchecked"})
public class IterableHelp
{
public <T> T[] toArray(Class<T> t, Iterable<T> elements)
{
final ArrayList<T> arrayElements = new ArrayList<T>();
for (T element : elements)
{
arrayElements.add(element);
}
final T[] ta = (T[]) Array.newInstance(t, arrayElements.size());
return arrayElements.toArray(ta);
}
}
Ответ 3
У вас большая проблема, чем непроверенное предупреждение. Фактически, он будет генерировать исключение ClassCastException во время выполнения, если T является чем-то другим, кроме Object.
Попробуйте String[] foo = IterableHelp.toArray(new ArrayList<String>());
Проще говоря, поскольку массивы содержат тип компонента во время выполнения, чтобы создать правильный T [], вы должны передать класс компонента в качестве другого аргумента (либо как сам класс T, либо T [], либо как объект T или T []) и использовать отражение для создания массива. Форма метода Collection
toArray()
, которая принимает аргумент, по этой причине принимает объект T [].