Spec-Zone .ru
спецификации, руководства, описания, API
След: Изучение Языка Java
Урок: (Обновленные) Обобщения
Вывод типа
Домашняя страница > Изучение Языка Java > (Обновленные) обобщения

Вывод типа

Вывод типа является возможностью компилятора Java смотреть на каждый вызов метода и соответствующее объявление, чтобы определить параметр типа (или параметры), которые делают вызов применимым. Алгоритм вывода определяет типы параметров и, при наличии, тип, что результат присваивается, или возвращается. Наконец, алгоритм вывода пытается найти наиболее определенный тип, который работает со всеми параметрами.

Чтобы проиллюстрировать этот последний тезис, в следующем примере, вывод решает, что второй параметр, который передают к методу pick, имеет тип String:

static <T> T pick(T a1, T a2) { return a2; }
Serializable s = pick("d", new ArrayList<String>());

Вывод типа и Универсальные Методы

Универсальные Методы, представленные Вы выводу типа, который позволяет Вам вызвать универсальный метод, поскольку Вы были бы обычный метод, не определяя тип между угловыми скобками. Рассмотрите следующий пример, BoxDemo, который требует Box class:

public class BoxDemo {

  public static <U> void addBox(U u, 
      java.util.List<Box<U>> boxes) {
    Box<U> box = new Box<>();
    box.set(u);
    boxes.set(box);
  }

  public static <U> void outputBoxes(java.util.List<Box<U>> boxes) {
    int counter = 0;
    for (Box<U> box: boxes) {
      U boxContents = box.get();
      System.out.println("Box #" + counter + " contains [" +
             boxContents.toString() + "]");
      counter++;
    }
  }

  public static void main(String[] args) {
    java.util.ArrayList<Box<Integer>> listOfIntegerBoxes =
      new java.util.ArrayList<>();
    BoxDemo.<Integer>addBox(Integer.valueOf(10), listOfIntegerBoxes);
    BoxDemo.addBox(Integer.valueOf(20), listOfIntegerBoxes);
    BoxDemo.addBox(Integer.valueOf(30), listOfIntegerBoxes);
    BoxDemo.outputBoxes(listOfIntegerBoxes);
  }
}

Следующее является выводом от этого примера:

Box #0 contains [10]
Box #1 contains [20]
Box #2 contains [30]

Универсальный метод addBox определяет один названный параметр типа U. Обычно, компилятор Java может вывести параметры типа универсального вызова метода. Следовательно, в большинстве случаев, Вы не должны определить их. Например, чтобы вызвать универсальный метод addBox, можно определить параметр типа следующим образом:

BoxDemo.<Integer>addBox(Integer.valueOf(10), listOfIntegerBoxes);

Альтернативно, если Вы опускаете параметры типа, компилятор Java автоматически выводит (от параметров метода), который параметр типа Integer:

BoxDemo.addBox(Integer.valueOf(20), listOfIntegerBoxes);

Вывод типа и Инстанцирование Универсальных Классов

Можно заменить параметры типа, требуемые вызвать конструктора универсального class с пустым множеством параметров типа (<>) пока компилятор может вывести параметры типа от контекста. Эту пару угловых скобок неофициально вызывают ромбом.

Например, рассмотрите следующее объявление переменной:

Map<String, List<String>> myMap = new HashMap<String, List<String>>();

Вы можете subsitute parameteried тип конструктора с пустым множеством параметров типа (<>):

Map<String, List<String>> my Map = newHashMap<>();

Отметьте, что, чтобы использовать в своих интересах вывод типа во время универсального инстанцирования class, Вы должны ромбовидная нотация. В следующем примере компилятор генерирует преобразование непроверенное, предупреждающее потому что HashMap() конструктор обращается к HashMap необработанный тип, не Map<String, List<String>> введите:

Map<String, List<String>> myMap = new HashMap(); // unchecked conversion warning

Java поддерживает ограниченный вывод типа для универсального создания экземпляра; можно только использовать вывод типа, если параметризованный тип конструктора очевиден из контекста. Например, следующий код не компилирует:

List<String> list = new ArrayList<>();
list.add("A");

// The following statement should fail since addAll expects
// Collection<? extends String>
list.addAll(new ArrayList<>());

Отметьте, что ромб часто работает в вызовах метода; однако, для большей ясности, предлагается, чтобы Вы использовали ромб прежде всего, чтобы инициализировать переменную, где это объявляется.

В сравнении, следующих компиляциях в качестве примера:

List<? extends String> list2 = new ArrayList<>();
list.addAll(list2);

Вывод типа и Универсальные Конструкторы Универсальных и Неуниверсальных Классов

Отметьте, что конструкторы могут быть универсальными (другими словами, объявите их собственные формальные параметры типа), и в универсальных и в неуниверсальных классах. Рассмотрите следующий пример:

class MyClass<X> {
  <T> MyClass(T t) {
    // ...
  }
}

Рассмотрите следующее инстанцирование class MyClass:

new MyClass<Integer>("")

Этот оператор создает экземпляр параметризованного типа MyClass<Integer>; оператор явно определяет тип Integer для формального параметра типа, X, из универсального class MyClass<X>. Отметьте, что конструктор для этого универсального class содержит формальный параметр типа, T. Компилятор выводит тип String для формального параметра типа, T, из конструктора этого универсального class (потому что фактический параметр этого конструктора является a String объект).

Компиляторы от выпусков до Java SE 7 в состоянии вывести фактические параметры типа универсальных конструкторов, подобных универсальным методам. Однако, компиляторы в Java, SE 7 и позже может вывести фактические параметры типа универсального class, который инстанцируют, если Вы используете ромб (<>). Рассмотрите следующий пример:

MyClass<Integer> myObject = new MyClass<>("");

В этом примере компилятор выводит тип Integer для формального параметра типа, X, из универсального class MyClass<X>. Это выводит тип String для формального параметра типа, T, из конструктора этого универсального class.


Отметьте: важно отметить, что алгоритм вывода использует только параметры вызова и, возможно, очевидный тип ожидаемого дохода, чтобы вывести типы. Алгоритм вывода не использует следствия позже в программе.

Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Обобщения, Наследование, и Подтипы
Следующая страница: Подстановочные знаки