Связаны ли дженерики с частью сигнатуры метода в Java?

Сегодня я понял, что это компилируется и работает нормально:

public class Test {
    public static <T> T handle(T val) {
        System.out.println("T");
        return val;
    }

    public static <T extends String> T handle(T val) {
        System.out.println("T extends String");
        return val;
    }
}

Два handle метода имеют одинаковое имя, одинаковое количество и тип (?) параметров. Единственное отличие состоит в том, что второй метод handle имеет более строгую общую границу. IDE вообще не жалуется, и код компилируется нормально. Во время выполнения метод выбирается должным образом - например, Test.handle("this is a string") вызовет второй метод, а Test.handle(10) вызовет первый.

Являются ли привязанные дженерики частью сигнатуры метода? или это магия разрешения перегрузки метода?


person Xinchao    schedule 20.07.2018    source источник
comment
Вкратце: <T extends String> удаляется до String, тогда как только <T> удаляется до Object, поэтому компилятор создаст два перегруженных метода: handle(Object) и handle(String), а в других местах эти методы можно выбрать в соответствии с типом аргумента.   -  person Pshemo    schedule 20.07.2018
comment
Официальное руководство по этой теме: Удаление общих методов   -  person Pshemo    schedule 20.07.2018


Ответы (2)


Обобщения обеспечивают безопасность типов во время компиляции; Во время выполнения ваши методы стираются до следующего:

public static Object handle(Object val) {
    System.out.println("T");
    return val;
}

public static String handle(String val) {
    System.out.println("T extends String");
    return val;
}

Из-за перегрузки метода handle(String) будет вызываться при передаче String, а handle(Object) будет вызываться при передаче любого другого Object (имейте в виду, что String является окончательным и не может иметь дочерних элементов).

person Jacob G.    schedule 20.07.2018

Рассмотрена граница дженериков.

В первом случае граница - это Object; во втором случае граница - String.

Когда типы стираются, граница используется вместо переменной типа, поэтому они становятся просто перегрузкой, принимающей (и возвращающей) параметры Object и String соответственно.

В этом нет ничего плохого.

person Andy Turner    schedule 20.07.2018