Те, що ви намагаєтеся зробити, дуже корисно, і я вважаю, що мені потрібно це робити дуже часто в коді, який я пишу. Приклад використання:
Скажімо, у нас є інтерфейс, Foo
і у нас є zorking
пакет, ZorkingFooManager
який створює і управляє екземплярами пакет-приватний 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.)