Прямое литье в петле foreach

Мне было интересно, возможно ли его напрямую подвергать объектам внутри цикла foreach.

Мы имеем следующие два класса: один из них расширяет другой:

class Book {};
class ExtendedBook extends Book {};

Теперь у нас есть массив книг, которые я хочу пропустить, потому что его поиск в расширенной книге я уверен, что все книги на самом деле являются расширенными. Есть ли способ напрямую их бросить?

Book [] books = bookSearch.getBooks("extendedBooks");

for (Book book: books){
   ExtendedBook eBook = (ExtendedBook) book;
   ....
}

Это включает два шага. Сначала зацикливайтесь на книгах и на втором шаге бросаете их. Можно ли сделать это за один шаг?

Что не работает:

// Directly assign it to a different type
for (ExtendedBook book : books){}

// Directly casting the array
ExtendedBooks [] eBooks = (ExtendedBooks []) books;

// Same goes for trying both in one step
for (ExtendedBook book : (ExtendedBook []) books){}

Я знаю, что это не настоящая боль, но сохранение цикла короче было бы приятным и, возможно, более читаемым, поскольку вы сохраняете фиктивную переменную, которая просто используется для кастинга вместо фактического действия.

Ответ 1

Я уверен, что вы не можете использовать в цикле, как хотите.

Ответ 2

Как использовать дженерики?

Напишите свою подпись в качестве:

<B extends Book> B [] getBooks(Class<B> bookType)

Теперь, если вы хотите искать книги типа ExtendedBook, просто вызовите:

ExtendedBooks [] eBooks = bookSearch.getBooks(ExtendedBook.class)

Не требуется никаких типов или других небезопасных вещей. Приятный и чистый.

Конечно, вам все равно нужно убедиться, что только ExtendedBook возвращает только такую ​​книгу, но похоже, что вы уже это решили.

Ответ 3

Подумайте о том, как отличить

ExtendedBook ex=(ExtendedBook)new Book();

Это принято компилятором, но JVM выбрасывает java.lang.ClassCastException, потому что этот тип кастинга неверен → Book не ExtendedBook, поэтому есть вероятность, что он не обработает потенциальные новые методы, добавленные в ExtendedBook класс.

По той же причине вы не можете сделать что-то вроде

ExtendedBook[] exbooksB=(ExtendedBook[]) new Book[10];

но может

Book[] booksA=new ExtendedBook[10];
ExtendedBook[] exbooks=(ExtendedBook[]) booksA;

Ответ 4

Вы не можете, потому что java не поддерживает неявную перегрузку преобразования, как в С#, с неявным оператором.