Как дженерики в java работают для следующей программы?

public class Program {

    private static <Program> void foo(Program x){
        System.out.println(x+"-->1");
    }

    private static void foo(final int i){
        System.out.println(i+"-->2");
    }

    public static void main(String[] args) {
        Integer i = 10;
        foo(i);
    }

}

И результат:

10-->1

Мне не удалось найти подходящую дискуссию по этой теме. Однако ответ на другую тему немного смутил меня: Возвращаемый тип общих методов Java

По их словам, общий <Program> не имеет ничего общего с типом возвращаемого значения, но в моем случае, если я немного изменюсь на эту программу, как показано ниже, результат отличается.

public class Program {

    private static <Integer> void foo(Program x){
        System.out.println(x+"-->1");
    }

    private static void foo(final int i){
        System.out.println(i+"-->2");
    }

    public static void main(String[] args) {
        Integer i = 10;
        foo(i);
    }

}

Вывод:

10-->2

Я использую JDK1.7

Ответы

Ответ 1

В вашем первом примере вы фактически не указываете аргумент типа Program, он является общим. Этот параметр типа не имеет ничего общего с вашим классом с именем Program. Вы получите тот же результат, создав опечатку следующим образом:

public class Program {

    private static <Programmmm> void foo(Programmmm x){
        System.out.println(x+"-->1");
    }

    private static void foo(final int i){
        System.out.println(i+"-->2");
    }

    public static void main(String[] args) {
        Integer i = 10;
        foo(i);
    }

}

Однако во втором примере параметр буквально имеет тип Program, и поэтому он не соответствует, когда вызывается как foo(10);, и вы получаете результат от второго метода.

Ответ 2

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

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

В терминах перегрузка метода, которая описывает порядок перегрузки. Это скажет вам, почему первая версия использует метод Object вместо метода int.

Вторая проблема заключается в том, что вы назвали ваши общие параметры конкретными типами, что запутывает. Легче понять, не делаете ли вы этого.

private static <T> void foo(T x){
    System.out.println(x+"-->1");
}

Теперь это яснее, T является параметризованным аргументом. В вашей второй версии

private static <T> void foo(Program x){
    System.out.println(x+"-->1");
}

Теперь ясно, что ваш аргумент должен быть объектом Program, а не только любым объектом.