// Object rl = exactl(raw); // Предупреждение // Непроверенное преобразование Holder в Holder
Object r3 = exactl(unbounded), // Должен возвращать Object Long r4 = exactl(bounded),
// Long r5 = exact2(raw, Ing); // Предупреждения-
// Непроверенное преобразование Holder в Holder
// Непроверенный вызов метода. exact2(Holder
// применяется к (Holder,Long)
Long гб = exact2(qualified, Ing),
// Long r7 = exact2(unbounded. Ing), // Ошибка-
// exact2(Holder
// (Holder
// Long r8 = exact2(bounded, Ing), // Ошибка.
// exact2(Holder
// к (Holder
// Long r9 = wildSubtype(raw, Ing); // Предупреждения
// Непроверенное преобразование Holder
// к Holder
// Непроверенный вызов метода-
// wildSubtype(Holder,T)
// применяется к (Holder.Long)
Long rlO = wildSubtype(qualified. Ing);
// Допустимо, но возвращать может только Object-
Object rll = wildSubtype(unbounded. Ing).
Long rl2 = wildSubtype(bounded. Ing).
// wildSupertype(raw, Ing); // Предупреждения. // Непроверенное преобразование Holder // к Holder // Непроверенный вызов метода: // wildSupertype(Holder,T) // применяется к (Holder.Long) wildSupertype(qualified, Ing), // wildSupertype(unbounded, Ing); // Ошибка:
// wildSupertype(Holder,T) не может
// применяться к (Holder
}
} ///:-
В методе rawArgs() компилятор знает, что Holder является параметризованным типом, поэтому несмотря на то, что здесь он выражен как низкоуровневый тип, компилятору известно, что передача Object методу set() небезопасна. Так как в данном случае используется низкоуровневый тип, методу set() можно передать объект произвольного типа, и он будет преобразован в Object. Таким образом, при использовании низкоуровневого типа вы лишаетесь проверки на стадии компиляции. Вызов get() демонстрирует ту же проблему: никакого Т нет, поэтому результатом может быть только Object.
Может создаться впечатление, что низкоуровневый Holder и Holder — приблизительно одно и то же. Однако метод unboundedArgs() демонстрирует различия между ними — в нем выявляются те же проблемы, но информация о них выдается в виде ошибок, а не предупреждений, поскольку низкоуровневый Holder может содержать разнородные комбинации типов, тогда как Holder содержит однородную коллекцию
В exactl() и exact2() используются точные параметры типов (то есть без метасимволов). Мы видим, что exact2() обладает иными ограничениями, нежели exactl(), из-за дополнительного аргумента.
В wildSubtype() ограничения на тип Holder опускаются до Holder с элементами любого типа, удовлетворяющими условию extends Т. И снова это означает, что Т может быть типом Fruit, a holder сможет вполне законно стать Holder
Реализация параметризованных интерфейсов
Класс не может реализовать две разновидности одного параметризованного интерфейса — вследствие стирания они будут считаться одним и тем же интерфейсом. Пример конфликта такого рода:
II: generics/MultiplelnterfaceVariants.java
II {CompileTimeError} (He компилируется)
interface Payable
class Employee implements Payable
class Hourly extends Employee
implements Payable
Класс Hourly компилироваться не будет, потому что стирание сокращает Payable
Преобразования типов и предупреждения