Преобразование не общего типа List в тип Generic List в Java 1.5
У меня есть список, который, как гарантируется, содержит только один объект типа. Это создается некоторым базовым кодом в библиотеке, которую я не могу обновить. Я хочу создать List <ObjectType> на основе входящего объекта List, чтобы мой код вызова говорил с List <ObjectType> .
Какой лучший способ преобразовать Список (или любую другую коллекцию объектов) в List <ObjectType> .
Ответы
Ответ 1
При взаимодействии с устаревшим кодом, который не задает параметры типа для общих типов, используйте шаблон. Например, предположим, что вы вызываете метод в старой библиотеке, которая просто возвращает raw Collection
:
Collection getItems();
В вашем коде присвойте результат переменной, объявленной с помощью подстановочного знака:
Collection<?> items = widget.getItems();
Таким образом, вы сохраняете безопасность типов, чтобы вы не получали никаких предупреждений.
Устаревший код может указывать (в комментарии, скорее всего), какие должны быть общие параметры. Например:
/**
* @return the items, as a Collection of {@link Item} instances.
*/
Collection getItems();
В этом случае у вас есть выбор. Вы можете привести результат к Collection<Item>
, но если вы это сделаете, вы полагаетесь на 100% на стороннюю библиотеку и отбрасываете уверенность в генерируемых типах Java: что любой ClassCastException
, созданный во время выполнения, будет происходить прямо на явное литье.
Что делать, если вы не полностью доверяете сторонней библиотеке, но все равно нужно создать Collection<Item>
? Затем создайте новую коллекцию и добавьте содержимое после их добавления к ожидаемому типу. Таким образом, если в библиотеке есть ошибка, вы сразу же узнаете об этом, вместо того, чтобы иметь некоторый код далеко и намного позже таинственно взорвали с помощью ClassCastException
.
Например:
Collection<?> tmp = widget.getItems();
Collection<Item> items = new ArrayList<Item>(tmp.size());
for (Object o : tmp)
items.add((Item) o); /* Any type error will be discovered here! */
В случае, когда параметр типа не известен во время компиляции, вы можете использовать фабрики коллекции, проверенные типом, в Collections
.
Ответ 2
Вы можете просто перечислить список:
List raw = new ArrayList();
List<String> generic = (List<String>) raw;
Ответ 3
Самый лучший и безопасный способ - использовать метод java.util.Collections 'checkedList (Список списка, Тип класса)'
С помощью этого метода все элементы в вашем старом списке будут проверены как можно раньше.
Ответ 4
Попробуйте следующее:
List<ObjectType> objectsWithType = Arrays.asList((ObjectType[])wildcardObjects).toArray());
Но помните, что это создаст список фиксированной длины. Если вы попытаетесь добавить или удалить элемент из этого списка, он выдает ошибку. Поэтому всегда будьте осторожны при использовании Arrays.asList()
.
Ответ 5
Если вы просто нажмете на List<T>
в любом старом месте, вы получите предупреждение о "непроверенном" компиляторе. Мы решили это, переместив его к утилитарному методу.
public class Lists {
@SuppressWarnings({"unchecked"})
public static <T> List<T> cast(List<?> list) {
return (List<T>) list;
}
}
Теперь вызывающий абонент не получает предупреждения, например:
for (Element child : Lists.<Element>cast(parent.getChildren())) {
// ...
}
Эта утилита checkedList
в теории представляет собой отличную идею, но на практике это отстойно проходить в классе, который вы ожидаете. Я надеюсь, что Java в конечном итоге получит информацию о типичной типизации во время выполнения.