— Ну, и напоследок еще одна маленькая лекция по Generic.
Сейчас я тебе расскажу, как обходить «стирание типов» (Type erasure).
— Ага. Мне тоже хочется это знать.
— Как ты уже наверное знаешь, в Java есть тип Class, который используется, чтобы хранить ссылку на объект класса. Примеры:
Class clazz = Integer.class;
Class clazz = String.class;
Class clazz = "abc".getClass();
— Ага.
Но вот чего ты, наверное, не знаешь, так это того, что есть еще один класс Class, который является Generic’ом. И переменные этого Generic Class’а могут хранить только ссылки на тип, который был типом-параметром. Примеры:
Class<Integer> clazz1 = Integer.class; //все отлично работает
Class<String> clazz2 = Integer.class; //ошибка компиляции.
Class<String> clazz1 = String.class; //все отлично работает
Class<String> clazz2 = int.class; //ошибка компиляции.
Class<? extends String> clazz1 = "abc".getClass(); //все отлично работает
Class<Object> clazz2 = "abc".getClass(); //ошибка компиляции.
— А почему оно так работает?
— Дело в том, что значение поля class у типа Integer (т.е. у Integer.class) – это на самом деле объект типа Class<Integer>.
Но давай пойдем дальше.
Так вот, пользуясь тем фактом, что Class<T> — это Generic, и тем, что переменная его типа может хранить значение только типа T, можно сделать вот такую хитрую комбинацию:
class Zoo<T>
{
Class<T> clazz;
ArrayList<T> animals = new ArrayList<T>();
Zoo(Class<T> clazz)
{
this.clazz = clazz;
}
public T createNewAnimal()
{
T animal = clazz.newInstance();
animals.add(animal);
return animal
}
}
Zoo<Tiger> zoo = new Zoo<Tiger>(Tiger.class); // вот тут передается тип!
Tiger tiger = zoo.createNewAnimal();
Это не мегахитрая комбинация – мы просто передаем ссылку на нужный тип. Но если бы мы просто пользовались Class вместо Class<T>, то кто-то мог по ошибке передать туда два разных типа – один в качестве параметра T, другой – в конструктор.
— Ага. Понимаю. Ничего сверхъестественного не произошло и страшного тоже. Ссылка на тип есть, пользоваться ей можно, работает и ладно.
— Вот, слышу слова «не мальчика, но мужа!» Работает и ладно – это часто самый оптимальный вариант.
Очень много всего можно было бы теперь переделать в Java, но нужно сохранять совместимость со старым кодом.
Именно десятки тысяч популярных отлаженных библиотек – это сегодня самый весомый аргумент в пользу Java. Так что, сохраняя обратную совместимость, Java остается самым популярным языком, и поэтому не может внедрять радикальные новшества.
— А я сделаю свою Java с блекджеком и …
— Ладно, я уже подустал за день. Давай до свидания.
— До свидания, Риша, и спасибо за такой интересный урок.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ