То, что вы пытаетесь сделать, очень полезно, и я считаю, что мне нужно делать это очень часто в коде, который я пишу.Пример использования:
Скажем, у нас есть интерфейс Foo
, и у нас есть пакет zorking
, который имеет ZorkingFooManager
, который создает и управляет экземплярами package-private ZorkingFoo implements Foo
.(Очень распространенный сценарий.)
Итак, ZorkingFooManager
должен содержать private Collection<ZorkingFoo> zorkingFoos
, но он должен предоставлять public Collection<Foo> getAllFoos()
.
Большинство Java-программистов не будут думать дважды перед реализациейgetAllFoos()
как выделение нового ArrayList<Foo>
, заполнение его всеми элементами из zorkingFoos
и возвращение его.Мне нравится развлекать мысль о том, что около 30% всех тактов, используемых Java-кодом, работающим на миллионах машин по всей планете, ничего не делают, кроме создания таких бесполезных копий списков ArrayList, которые представляют собой микросекунды, собираемые мусором после их создания.
Решением этой проблемы, конечно же, является уменьшение коллекции.Вот лучший способ сделать это:
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
, очевидно, можно использовать его в присваивании, поэтому дополнительная переменная «result» решает эту проблему.(В любом случае он должен быть оптимизирован либо компилятором, либо JIT.)