То, что вы пытаетесь сделать, очень полезно, и я считаю, что мне нужно делать это очень часто в коде, который я пишу. Пример использования:
Скажем, у нас есть интерфейс, Foo
и у нас есть zorking
пакет, ZorkingFooManager
который создает и управляет экземплярами package-private.ZorkingFoo implements Foo
. (Очень распространенный сценарий.)
Итак, он ZorkingFooManager
должен содержать, private Collection<ZorkingFoo> zorkingFoos
но должен предоставлятьpublic Collection<Foo> getAllFoos()
.
Большинство java-программистов не стали бы дважды думать перед тем, getAllFoos()
как реализовать как выделение нового ArrayList<Foo>
, заполнение его всеми элементами изzorkingFoos
и возвращение. Мне нравится думать, что около 30% всех тактовых циклов, потребляемых java-кодом, работающим на миллионах машин по всей планете, ничего не делают, кроме создания таких бесполезных копий ArrayLists, которые собираются через микросекунды после их создания.
Решением этой проблемы, конечно же, является низведение коллекции. Вот лучший способ сделать это:
static <T,U extends T> List<T> downCastList( List<U> list )
{
return castList( list );
}
Это подводит нас к castList()
функции:
static <T,E> List<T> castList( List<E> list )
{
@SuppressWarnings( "unchecked" )
List<T> result = (List<T>)list;
return result;
}
Промежуточная result
переменная необходима из-за извращения языка java:
return (List<T>)list;
выдает исключение "непроверенное приведение"; Все идет нормально; но потом:
@SuppressWarnings( "unchecked" ) return (List<T>)list;
является незаконным использованием аннотации подавления предупреждений.
Таким образом, даже несмотря на то, что использование @SuppressWarnings
в return
операторе некошерно , очевидно, что его можно использовать в присваивании, поэтому дополнительная переменная «результат» решает эту проблему. (В любом случае его следует оптимизировать либо компилятором, либо JIT.)