Из этих примеров видно, что неопределенные типы S, T могут быть типами параметров конструкторов и типами возвращаемых методами значений. Разумеется, они могут быть типами параметров не только конструкторов, но и любых методов. Более того, типами параметров и типами возвращаемых значений методов могут быть настраиваемые типы. Можно написать метод в такой форме:

public MyGenericClass2 makeClass2(S id,

MyGenericClass data){ return new MyGenericClass2(id, data.getData());

}

и обратиться к нему так, как показано в листинге 4.3.

Листинг 4.3. Настраиваемые классы — параметры методов

public class MyGenericClass2Demo{

public MyGenericClass2

makeClass2(S id, MyGenericClass data){

return new MyGenericClass2(id, data.getData());

}

public static void main(String[] args){

MyGenericClass dMyGen = new MyGenericClass<>(34.456);

MyGenericClass2Demo d = new MyGenericClass2Demo<>();

MyGenericClass2 ldMyGen2 = d.makeClass2(123456L, dMyGen);

}

}

Шаблон типа (wildcard type)

В предыдущих главах мы часто пользовались тем, что можно определить ссылку типа суперкласса, ссылающуюся на объект подкласса, например:

Number n = new Long(123456L);

Number d = new Double(27.346);

Более того, это свойство распространяется на массивы:

Number[] n = new Long[100];

Можно ли распространить эту возможность на настраиваемые типы? Например, можно ли написать последний оператор листинга 4.3 так:

MyGenericClass2 n = // Сшибка!

d.makeClass2(123456L, dMyGen);

Ответ отрицательный. Из того, что какой-то класс B является подклассом класса A, не следует, что класс g будет подклассом класса g.

Это непривычное обстоятельство вынудило ввести дополнительную конструкцию — шаблон типа (wildcard type), применяемую в процессе настройки типа. Шаблон типа обозначается вопросительным знаком и означает "неизвестный тип" или "произвольный тип". Предыдущий код не вызовет возражений у компилятора, если написать его в таком виде:

MyGenericClass2 n = // Верно.

d.makeClass2(123456L, dMyGen);

или

MyGenericClass2 n = // Верно.

d.makeClass2(123456L, dMyGen);

Можно написать даже неограниченный шаблон типа

MyGenericClass2 n =

d.makeClass2(123456L, dMyGen);

Такая запись будет почти эквивалентна записи

MyGenericClass2 n =

d.makeClass2(123456L, dMyGen);

за тем исключением, что в первом случае компилятор сделает более строгие проверки.

Кроме записи , означающей "произвольный подтип типа Type, включая сам тип Type", можно написать выражение , означающее "произвольный супертип типа Type, включая сам тип Type".

Шаблон типа можно использовать в тех местах кода, где настраивается тип, в том числе в параметрах метода:

public MyGenericClass2 makeClass2(S id,

MyGenericClass data){

return new MyGenericClass2(id, data.getData());

}

но, поскольку шаблон типа не является типом, его нельзя применять для создания объектов и массивов. Следующие определения неверны:

Average a = // Ошибка!

new Average(iArray);

Average[] a = // Ошибка!

new Average[10];

Тем не менее при определении массива (но не объекта) можно записать неограниченный шаблон типа:

Average[] a = // Верно.

new Average[10];

Настраиваемые методы

Настраиваемыми могут быть не только типы, но и методы. Параметры настраиваемого метода (type parameters) указываются в заголовке метода в угловых скобках перед типом возвращаемого значения. Это выглядит так, как показано в листинге 4.4.

Листинг 4.4. Настраиваемый метод

public class MyGenericClass2Demo{

public MyGenericClass2

makeClass2(S id, MyGenericClass data){

return new MyGenericClass2(id, data.getData());

} public static void main(String[] args){

MyGenericClass dMyGen = new MyGenericClass(34.456);

MyGenericClass2Demo d =

new MyGenericClass2Demo();

MyGenericClass2 ldMyGen2 = d.makeClass2(123456L, dMyGen);

}

}

Метод makeClass2 () описан в простом, ненастраиваемом, классе MyGenericClass2Demo, и его параметры задаются в угловых скобках . Здесь можно записывать ограниченные параметры

public

MyGenericClass2 makeClass2(S id, MyGenericClass data){

return new MyGenericClass2(id, data.getData());

}

Как видно из листинга 4.4, специально настраивать метод не нужно, конкретные типы его параметров и возвращаемого значения определяются компилятором по переданным в метод аргументам.

Перейти на страницу:

Все книги серии В подлиннике

Похожие книги