Эккель Брюс
Шрифт:
Для получения типизованного списка объектов Class требуется преобразование типа, что приводит к выдаче предупреждения на стадии компиляции. Метод loader определяется отдельно и размещается в секции статической инициализации, потому что директива @SuppressWarnings не может располагаться прямо в секции статической инициализации.
Для подсчета объектов Pet нам понадобится механизм подсчета их разных видов. Для этой цели идеально подойдет карта (Map), в которой ключами являются имена типов Pet, а значениями — переменные Integer с количеством Pet. Например, это позволит получать ответы на вопросы типа «сколько существует объектов Hamster?». При подсчете Pet будет использоваться ключевое слово instanceof:
II: typeinfo/PetCount.java II Использование instanceof. import typeinfo.pets.*; import java util.*;
import static net.mindview.util.Print.*,
public class PetCount {
static class PetCounter extends HashMap<String,Integer> { public void count(String type) {
Integer quantity = get(type); if(quantity == null) put(type, 1);
else
put(type, quantity +1),
}
}
public static void
countPets(PetCreator creator) {
PetCounter counter= new PetCounter, for(Pet pet : creator.createArray(20)) { // Подсчет всех объектов Pet: printnb(pet.getClass.getSimpleNameO + " "), if(pet instanceof Pet)
counter.count("Pet"); if(pet instanceof Dog)
counter.count("Dog"); if(pet instanceof Mutt)
counter count("Mutt"), if(pet instanceof Pug)
counter countC'Pug"); if(pet instanceof Cat)
counter.count("Cat"); if(pet instanceof Manx)
counter count("EgyptianMau"); if(pet instanceof Manx)
counter.count("Manx"); if(pet instanceof Manx)
counter.count("Cymric"). if(pet instanceof Rodent)
counter.count("Rodent"), if(pet instanceof Rat)
counter count("Rat"); if(pet instanceof Mouse)
counter.count("Mouse"); if(pet instanceof Hamster)
counter.count("Hamster"),
}
// Вывод результатов подсчета.
printO;
print(counter);
}
public static void main(String[] args) { countPets(new ForNameCreator);
}
} /* Output-
Rat Manx Cymric Mutt Pug Cymric Pug Manx Cymric Rat EgyptianMau Hamster EgyptianMau Mutt
Mutt Cymric Mouse Pug Mouse Cymric
{Pug=3. Cat=9, Hamster=l, Cymric=7, Mouse=2, Mutt=3, Rodent=5, Pet=20, Manx=7,
EgyptianMau=7, Dog=6, Rat=2}
*///:-
В countPets массив случайным образом заполняется объектами Pet с использованием PetCreator. Затем каждый объект Pet в массиве тестируется и подсчи-тывается при помощи instanceof.
У ключевого слова instanceof имеется одно серьезное ограничение: объект можно сравнивать только с именованным типом, но не с объектом Class. Возможно, вам показалось, что в предыдущем примере перебор всех выражений instanceof выглядит неудобно и громоздко, и вы правы. Тем не менее автоматизировать этот процесс невозможно — создать из объектов Class список ArrayList и сравнивать объекты по очереди с каждым его элементом не получится (к счастью, существует альтернативное решение, но это попозже). Впрочем, особенно горевать по этому поводу не стоит — если вам приходится записывать множество проверок instanceof, скорее всего, изъян кроется в архитектуре программы.
Использование литералов class
Если записать пример PetCreator.java с использованием литералов class, программа во многих отношениях становится более понятной:
//• typeinfo/pets/LiteralPetCreator.java // Using class literals package typeinfo pets, import java util.*;
public class LiteralPetCreator extends PetCreator { // Блок try не нужен @SuppressWarnings("unchecked")
public static final List<Class<? extends Pet» all Types = Col 1 ections unmodi fi ableLi st(Arrays.asLi st(
Pet.class, Dog class. Cat.class, Rodent.class, Mutt class. Pug.class. EgyptianMau.class. Manx.class. Cymric class. Rat.class. Mous'e.class.Hamster.class)); // Типы для случайного создания: private static final List<Class<? extends Pet» types = al1 Types.subLi st(al1 Types.i ndexOf(Mutt.class). allTypes.sizeO); public List<Class<? extends Pet» types { return types;
}
public static void main(String[] args) { System.out.printin(types);
}
} /* Output:
[class typeinfo pets.Mutt, class typeinfo.pets.Pug. class typeinfo.pets.EgyptianMau. class typeinfo pets Manx, class typeinfo.pets.Cymric, class typeinfo.pets.Rat, class typeinfo.pets.Mouse, class typeinfo.pets.Hamster] *///.-
В будущем примере PetCount3.java контейнер Map заполняется всеми типами Pet (не только генерируемыми случайным образом), поэтому нам понадобился список allTypes. Список types представляет собой часть allTypes (создается вызовом List.subList) со всеми типами Pet, поэтому он используется для случайного генерирования Pet.
На этот раз при создании types блок try не нужен, так как необходимые проверки типов проводятся еще во время компиляции и исключения не возбуждаются, в отличие от метода Class.forName.