Как определить метод, который получает два аргумента типа T и S, который расширяет T в Java? - PullRequest
0 голосов
/ 03 мая 2018

При изучении обобщений Java мне было интересно, возможно ли объявить метод, который получает два аргумента, первый из которых имеет универсальный тип T, а второй - универсальный тип S, который расширяется (или является тем же введите as) T. Поэтому я начал экспериментировать с этим и написал следующее объявление метода:

public static <T, S extends T> void testMethod(T t, S s)
{
    System.out.println("We are inside testMethod.");
}

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

java.lang.Integer num1 = new java.lang.Integer(0);
java.lang.Integer num2 = new java.lang.Integer(1);

testMethod(num1, num2);
testMethod(num1, new Object());

ожидание, что второй вызов вызовет исключение времени компиляции. Но программа была скомпилирована и запущена без ошибок. Затем я изменил объявление метода testMethod следующим образом:

public <T extends java.lang.Number, S extends T> void testMethod(T t, S s)

со следующими звонками:

testMethod(new Integer(0), new Double(1.1));
testMethod(new Integer(0), new Object());

Первый вызов не содержит ошибок, но второй вызывает ошибку во время компиляции. Кажется, что, пока t и s являются подтипами java.lang.Number, ошибки не возникает, является ли s подтипом t или нет.

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

1 Ответ

0 голосов
/ 03 мая 2018

Есть две проблемы:

  1. С точки зрения обобщений, любой тип является подтипом самого себя. Нет способа объявить S extends T таким, что S и T не могут быть одного типа. Кроме того, даже если бы это было возможно, это не имело бы большого эффекта, потому что любой экземпляр S мог бы также быть передан как T.

  2. Вывод типа делает все возможное, чтобы метод компилировался. Если S несовместим с типом первого аргумента, компилятор выведет ближайшего общего предка как T. Вы можете избежать этой проблемы, явно указав T при вызове метода:

    ThisClass.<Integer, Integer>testMethod(1, 2);    // compiles
    ThisClass.<Integer, Integer>testMethod(1, 2.0);  // does not compile
    

Дело в том, что, в конечном счете, сам метод не может обеспечить выполнение требования, согласно которому S является подтипом (или даже совместимым с) типом t. Я не думаю, что есть способ обойти это.

...