Подтвердить что ты не робот

Многоразовый метод преобразования 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 использует непроверенные или небезопасные операции.'

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

4b9b3361

Ответ 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 [].