Почему этот общий метод не дает ошибки времени компиляции?

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

class GenericMethodDemo {

    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;

    }

    public static void main(String args[]) {

        Integer nums[] = {1, 2, 3, 4, 5};

        if (!isIn("2", nums)) {
            System.out.println("2 is not in nums");
        }
    }
}

person Ankit Srivastava    schedule 19.09.2017    source источник
comment
Не используйте необработанные типы, если хотите, чтобы компилятор знал о ваших дженериках.   -  person azurefrog    schedule 19.09.2017
comment
Попробуйте GenericMethodDemo.<String, Integer>isIn("2", nums), и вы получите ошибку компилятора относительно несоответствия границ.   -  person azurefrog    schedule 19.09.2017
comment
почему это не дает ошибки в этой форме   -  person Ankit Srivastava    schedule 19.09.2017
comment
Ну, для начала компилятор может просто сделать T и V равными Object.   -  person Louis Wasserman    schedule 19.09.2017


Ответы (1)


Это компилируется без ошибок, поскольку система типов выводит ближайший общий супертип между двумя аргументами типа.

В приведенном примере ближайшим общим супертипом является Object.

Если мы укажем двойное значение в качестве первого параметра, Number будет выведенным типом, поскольку это ближайший общий супертип между Double и Integer.

public static void main(String args[]) {

    Integer nums[] = {1, 2, 3, 4, 5};

    //In this case the nearest common type is object
    if (!isIn("2", nums)) {
        System.out.println("2 is not in nums");
    }

    //In this case the nearest common type would be Number
    if (!isIn(2d, nums)) {
        System.out.println("2 is not in nums");
    }        
}

Как заявил azurefrog, для предотвращения использования свидетелей типа компиляции (GenericMethodDemo.<String, Integer>isIn("2", nums)) для предотвращения использования ближайшего общего супертипа при выводе типа.

Подробности спецификации языка Java относительно вывода типов можно найти здесь: https://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html

person Jeff    schedule 19.09.2017