Как определяется тип данных параметра типа в ковариации и контравариантности? - PullRequest
5 голосов
/ 23 марта 2012

Я читал книгу «Дженерики и коллекции Явы» Мориса Нафталина, Филиппа Уодлера, и в первых двух главах у меня кончились сомнения. Я не смог выяснить ответы.

При звонке:

 public static <T> void copy(List<? super T> dst, List<? extends T> src) {
 for (int i = 0; i < src.size(); i++) {
 dst.set(i, src.get(i));
 }
}


 List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
 List<Integer> ints = Arrays.asList(5, 6);
 Collections.copy(objs, ints);
 assert objs.toString().equals("[5, 6, four]");

Во время вызова функции «Копировать»:
1-й параметр:? = Объект
2-й параметр:? = Целое число

Но каков тип данных T? Как это решает jvm на основе реализации стирания?

В книге сказано, что: В строке Collections.copy (obj, ints) параметр типа T принимается за Number. Вызов разрешен, потому что objs имеет тип List , который является подтипом List <? super Number> (поскольку Object является супертипом Number, как того требует супер), а ints имеет тип List , который является подтипом List <? extends Number> (поскольку Integer является подтипом Number, как того требует подстановочный знак extends).

Но поскольку Integer реализует и Serializable, и Comparable, aprt из расширяющегося класса Number и класса Object также является супертипом Serializable и Comparable.

Так почему бы и нет, чтобы T воспринимался как Сериализуемый или Сравнимый вместо Числа, потому что Принцип Подстановки позволит его использовать.

Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 23 марта 2012

http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf

Из «простого» примера JLS говорит, что выбирает наиболее конкретный тип, который удовлетворяет всем создаваемым ограничениям.

15.12.2.7 Аргументы типа, основанные на фактических аргументах

Ограничение супертипа T:> X подразумевает, что решение является одним из супертипы X. Учитывая несколько таких ограничений на T, мы можем пересечь наборы супертипов, подразумеваемых каждым из ограничений, так как Параметр типа должен быть членом всех из них. Затем мы можем выбрать наиболее конкретный тип, который находится на пересечении

Copy.java:11: incompatible types
found   : java.lang.Integer[]
required: java.lang.String[]
    String[] res = copy(Arrays.<Object>asList(2, 3.14, "four"), Arrays.asList(5, 6));
                       ^
1 error
➜  /tmp  cat Copy.java 
import java.util.*;
public class Copy {
public static <T> T[] copy(List<? super T> dst, List<? extends T> src) {
   for (int i = 0; i < src.size(); i++) {
      dst.set(i, src.get(i));
   }

   return null;
  }
  public static void main(String[] args) {
    String[] res = copy(Arrays.<Object>asList(2, 3.14, "four"), Arrays.asList(5, 6));
  }

}
1 голос
/ 23 марта 2012

T определяется на основе аргументов, но может быть также указано явно.Так что, да, это может быть Comparable и Serializable.

Все они действительны:

     Collections.<Number>copy(objs, ints);
     Collections.<Comparable>copy(objs, ints);
     Collections.<Serializable>copy(objs, ints);
     Collections.<Integer>copy(objs, ints);

     Collections.copy(objs, ints); // implicitly Integer

Когда тип не указан, целое число выбирается из-за способа обработки и объяснения <? extends Integer>в документации Java

0 голосов
/ 23 марта 2012

Класс объекта является также супер типом Serializable и Comparable
Это не так, Serializable и Comparable являются интерфейсами и не имеют отношения к Object.

Кроме того, super ? является точным обратным extends ? , что означает, что его нельзя применять к интерфейсам. его можно применять к интерфейсам.

Когда вы пишете ? extends Tозначает, что ? является неизвестным подтипом T, вероятно, T сам .Я считаю, что JVM разрешает снизу вверх, что означает T на самом деле Integer, а не Number (поправьте меня, если я ошибаюсь).

Тогда

   Collections.copy(objs, ints)

на самом деле

   Collections.<Integer>(objs, ints)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...