В чем разница между Java 8 и Java 7, относящимися к методам generi c в привязке параметра типа? - PullRequest
0 голосов
/ 20 января 2020
public class GenMethodDemo2 {
    static <T, V extends T> boolean isIn(T x, V[] y){
        for (int i = 0; i < y.length; i++) {
            if (x.equals(y[i])) return true;
        }
        return false;
    }

    @Test
    public void test(){
        Integer[] nums = {1,2,3,4,5};
        if(isIn("java",nums)) System.out.println("java is in nums");
        if(!isIn("java",nums)) System.out.println("java is not in nums");
    }
}

, когда я использую jdk8, этот код работает хорошо, и результат равен java is not in nums

, но когда я перехожу на jdk7, тот же код не будет соответствовать ie, и сообщение будет отображаться Inferred type 'java.lang.Integer' for type parameter 'V' is not within its bound; should extend 'java.lang.String'

я хочу знать: как jdk8 может компилировать ie этот код, когда функция явно определяет тип параметра bounded V extends T?

Ответы [ 2 ]

2 голосов
/ 21 января 2020

Я считаю, что есть некоторые улучшения в выводе типов для обобщенных c методов в Java 8 по сравнению с Java 7, хотя я не уверен, что это объяснит разницу, которую вы видите. В любом случае, когда логический вывод завершается неудачно, вы всегда можете явно указать свидетеля типа, чтобы доказать компилятору, что существует тип, где границы будут встречаться, например:

if (GenMethodDemo2.<Object, Integer>isIn("java",nums))
    System.out.println("java is in nums");

В этом случае оба типа переменные T и V всегда могут быть выбраны равными Object, и они не будут принимать меньшее количество параметров (поскольку любой T будет подтипом Object, а любой V[] будет подтип Object[]). Так что вашему методу на самом деле не нужны никакие дженерики:

static boolean isIn(Object x, Object[] y){
    for (int i = 0; i < y.length; i++) {
        if (x.equals(y[i])) return true;
    }
    return false;
}
1 голос
/ 21 января 2020

Подпись типа

static <T, V extends T> boolean isIn(T x, V[] y)

не намного лучше, чем

static boolean isIn(Object x, Object[] y)

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

Следовательно, когда вы меняете метод на

@Test
public void test(){
    Integer[] nums = {1,2,3,4,5};
    if(GenMethodDemo2.<Object,Integer>isIn("java",nums))
            System.out.println("java is in nums");
    if(!GenMethodDemo2.<Object,Integer>isIn("java",nums))
            System.out.println("java is not in nums");
}

, он может быть скомпилирован во всех Java версиях, которые поддерживают Generics.

Из-за ковариантных массивов также будет работать указание

if(GenMethodDemo2.<Object,Object>isIn("java",nums))
        System.out.println("java is in nums");
if(!GenMethodDemo2.<Object,Object>isIn("java",nums))
        System.out.println("java is not in nums");

Вывод типа Java 8 не меняет, какой вызов метода допустим, он только упрощает выполнение допустимых вызовов , поскольку у вас меньше сценария ios, где вам нужно явно указать аргументы типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...