Дано
List<Fruit> getFruits() {...}
Вы не можете выполнить тип
List<Orange> oranges = (List<Orange>) getFruits();
Из-за стирания типа во время выполнения тип getFruits просто List.Компилятор даже не позволит вам сделать уныние (у меня были сомнения, поэтому я попробовал в Eclipse, прежде чем ответить).
Вы можете сказать компилятору, что ваш список будет содержать некоторый подкласс Fruit, в этом случае вам нужно использовать метод подстановки для вас:
List<? extends Fruit> getFruits() {...}
Тогда приведение становится возможным,но с предупреждением о безопасности типа:
@SuppressWarnings("unchecked")
List<Orange> oranges = (List<Orange>) getFruits();
Учитывая, что тип времени выполнения getFruits равен List, вы можете просто отбросить информацию о типовых типах и использовать небезопасное назначение:
@SuppressWarnings("unchecked")
List<Orange> oranges = (List) getFruits();
Возможно, это более элегантный способ, поскольку он четко определяет ваше намерение, хотя для этого потребуется больше системных ресурсов:
List<Orange> oranges = Arrays.asList((Orange[])getFruits().toArray())
Массивы в Java сохраняют информацию о типе во время выполнения, поэтому приведение является действительным и«безопасный» с точки зрения компилятора, но он может выдать исключение времени выполнения, если вы пропустите несколько яблок в корзине с фруктами.