Вместо того, чтобы передавать тип списка, который вы хотите создать, почему бы просто не передать пустую коллекцию , которую вы хотите заполнить? Это дает пользователям вашего API гораздо больше гибкости, так как использование конструктора по умолчанию не всегда идеален. (например, возможно, мне нужен набор, в котором я предоставляю ожидаемое количество элементов, или я хочу отсортированный список, в котором я предоставляю компаратор).
Кроме того, как примечание, вы всегда должны программировать на максимально общий интерфейс. В этом случае ваши входные данные не должны быть более конкретными, чем Iterable, а ваши выходные данные - коллекцией.
Учитывая это, я бы написал метод следующим образом -
public static <T, C extends Collection<T>> C typesafeAdd(Iterable<?> from, C to, Class<T> listClass) {
for (Object item: from) {
to.add(listClass.cast(item));
}
return to;
}
тогда код вызова выглядит так:
<code> public static void main(String[] args) {
List<?> untypedStringList = LegacyApi.getStringList();
List<String> typesafeStringList = typesafeAdd(untypedStringList, new ArrayList<String>(), String.class);
}
2 комментария здесь:
- Если вы действительно можете доверять LegacyApi (или какому-либо другому, предоставившему вам нетипизированный список), чтобы он возвращал вам коллекцию только с ожидаемым типом, тогда вы можете просто выполнить неконтролируемое приведение и подавить его. Это должно быть локализовано в наименьшей возможной области. то есть: создать что-то вроде TypesafeLegacyApiWrapper, которое делегирует вызовы LegacyApi.
- Эта сигнатура метода все еще ломается, если у вас есть что-то более сложное. Например, если у вас есть List >, этот метод не работает.