Java Generics (подстановочные знаки)

У меня есть пара вопросов об общих подстановочных знаках в Java:

  1. В чем разница между List List и List List ?

  2. Что такое ограниченный шаблон и что является неограниченным шаблоном?

В вашем первом вопросе и являются примерами ограниченных подстановочных знаков. Неограниченный шаблон выглядит как , И в основном означает . Это свободно означает, что общим может быть любой тип. Ограниченный подстановочный знак ( или ) помещает ограничение на тип, говоря, что он либо должен расширять определенный тип ( известен как верхняя граница), либо должен быть предком определенного типа ( известен как нижняя граница).

В учебниках Java есть довольно хорошие объяснения дженериков в статьях Wildcards и More Fun с подстановочными знаками .

Если у вас есть иерархия classов A, B – подclass A, а C и D оба являются подclassами B, как показано ниже

 class A {} class B extends A {} class C extends B {} class D extends B {} 

затем

 List la; la = new ArrayList(); la = new ArrayList(); la = new ArrayList(); List lb; lb = new ArrayList(); //fine lb = new ArrayList(); //will not compile public void someMethod(List lb) { B b = lb.get(0); // is fine lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B } public void otherMethod(List lb) { B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List and only contain instances of A lb.add(new B()); // is fine, as we know that it will be a super type of A } 

Ограниченный подстановочный знак ? extends B ? extends B где B – некоторый тип. То есть тип неизвестен, но на нем может быть помечена «привязка». В этом случае он ограничен некоторым classом, который является подclassом B.

Джош Блох также имеет хорошее объяснение того, когда использовать super и extends этот видеоролик google io, где он упоминает, что продюсер extends потребительскую мнемонику.

С презентационных слайдов:

Предположим, вы хотите добавить массовые методы в Stack

void pushAll(Collection src);

– src является производителем E

void popAll(Collection dst);

– dst является потребителем E

Могут быть случаи, когда вы захотите ограничить типы типов, которым разрешено передавать параметр типа. Например, метод, который работает с числами, может только принимать экземпляры Number или его подclassов. Для этого используются параметры ограниченного типа.

 Collection 

означает, что он может принимать все объекты, у которых есть связь IS-A с MyObject (т.е. любой объект, который является типом myObject, или мы можем сказать любой объект любого подclassа MyObject) или объект classа MyObject.

Например:

 class MyObject {} class YourObject extends MyObject{} class OurObject extends MyObject{} 

Затем,

 Collection myObject; 

будет принимать только MyObject или дочерние объекты MyObject (т. е. любой объект типа OurObject или YourObject или MyObject, но не любой объект суперclassа MyObject).

В целом,

Если структура содержит элементы с типом формы ? extends E ? extends E , мы можем получить элементы из структуры, но мы не можем поместить элементы в структуру

 List ints = new ArrayList(); ints.add(1); ints.add(2); List nums = ints; nums.add(3.14); // compile-time error assert ints.toString().equals("[1, 2, 3.14]"); 

Чтобы поместить элементы в структуру, нам нужен еще один вид подстановочных знаков под названием Wildcards with super ,

  List objs = Arrays.asList(2, 3.14, "four"); List ints = Arrays.asList(5, 6); Collections.copy(objs, ints); assert objs.toString().equals("[5, 6, four]"); public static  void copy(List dst, List src) { for (int i = 0; i < src.size(); i++) { dst.set(i, src.get(i)); } } 

Предварительно требования

 public class A { } public class B extends A { } public class C extends A { } List listA = new ArrayList(); List listB = new ArrayList(); 

Проблема

 listB = listA; //not compiled listA = listB; //not compiled 

listB = listA; В ListA вы можете вставлять объекты, которые являются либо экземплярами A, либо подclassами A (B и C). Тогда вы можете рискнуть, что listA содержит объекты, отличные от B. Когда вы пытаетесь взять объекты из listB вы можете рискнуть получить объекты вне B (например, A или C). Это нарушает договор listB переменной listB .

listA = listB; Если вы можете выполнить это задание, можно было бы вставить экземпляры A и C в список, на который указывает listB . Вы можете сделать это с помощью ссылки listA , которая объявлена ​​как List. Таким образом, вы можете вставить объекты, отличные от B, в список, объявленный для хранения экземпляров B (или B подclassа).

objective

При создании многоразовых методов, которые работают с коллекциями определенного типа.

Вы должны использовать List List ( верхняя граница ), если вы собираетесь читать .get () из списка

Когда вы знаете, что экземпляры в коллекции имеют экземпляры A или подclassов A, можно безопасно прочитать экземпляры коллекции и передать их экземплярам A.

Вы не можете вставлять элементы в список, потому что вы не знаете, введен ли список в class A, B или C.

Вы должны использовать List List ( нижняя граница ), если вы собираетесь вставить .add () в список

Когда вы знаете, что список набирается либо A, либо суперclass A, можно вставить экземпляры A или подclassы A (например, B или C) в список.

Однако вы не можете читать из списка, за исключением случаев, когда он передает объекты чтения объекту. Элементы, уже присутствующие в списке, могут быть любого типа, который является либо A, либо суперclassом A, но невозможно точно знать, какой class он есть.

Пожалуйста, прочитайте больше здесь – http://tutorials.jenkov.com/java-generics/wildcards.html

Создаются общие шаблоны для создания методов, которые работают с коллекцией более многократно.

Например, если метод имеет параметр List , мы можем предоставить этот метод только List . В некоторых случаях это пустая трата для этого метода:

  1. Если этот метод только считывает объекты из List , нам следует предоставить этот List . (Поскольку A-sub IS a A)
  2. Если этот метод только вставляет объекты в List , нам следует разрешить этот List . (Потому что A IS A-super)
Давайте будем гением компьютера.