Почему один класс действителен, а другой нет? - PullRequest
3 голосов
/ 24 июня 2010

Как видите, важно иметь тип, отличный от void.

class TestValid {

public String f(List<String> list) {
    return null;
}

public Integer f(List<Integer> list) {
    return null;
}

public void test() {
    f(Arrays.asList("asdf"));
    f(Arrays.asList(123));
}

}

class TestInvalid {

public void f(List<String> list) {
    System.out.println("strings");
}

public void f(List<Integer> list) {
    System.out.println("numbers");
}

}

Ответы [ 5 ]

7 голосов
/ 24 июня 2010

TestValid недопустимо для начала:

TestValid.java:9: name clash: f(List<Integer>) and f(List<String>)
have the same erasure
public Integer f(List<Integer> list) {
               ^

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

// Equally invalid
public Integer f() {}
public String f() {}

Если вам действительно удалось получить TestValid для компиляции, мне было бы интересно узнать, какой компилятор вы используете.

1 голос
/ 24 июня 2010

Во втором случае методы f невозможно различить во время выполнения из-за стирания типа.

http://java.sun.com/docs/books/tutorial/java/generics/erasure.html

Таким образом, они оба имеют точно одинаковую сигнатуру.

0 голосов
/ 09 декабря 2011

Ковариантный тип возврата до JDK1.5 не поддерживается; подумайте о методе Object.clone (). Следующее может представлять интерес:

public class Base {
    public String f_array(List<String> strings) {
        StackTraceElement current = Thread.currentThread().getStackTrace()[1];
        System.out.println(String.format("%s#%s(strings)", current.getClassName(), current.getMethodName()));
        return null;
    }

    public Integer f_array(List<Integer> ints) {
        StackTraceElement current = Thread.currentThread().getStackTrace()[1]; 
        System.out.println(String.format("%s#%s(ints)", current.getClassName(), current.getMethodName()));
        return null;
    }

    public Number f() {
        StackTraceElement current = Thread.currentThread().getStackTrace()[1]; 
        System.out.println(String.format("%s#%s()", current.getClassName(), current.getMethodName()));
        return null;
    };

    public static class Child extends Base {
        @Override
        public Integer f() { //note Integer is_a Number
            StackTraceElement current = Thread.currentThread().getStackTrace()[1]; 
            System.out.println(String.format("%s#%s()", current.getClassName(), current.getMethodName()));
            return null;
        }
    }

    public static void main(String... args) {
        Base c = new Base();
        c.f_array(Arrays.asList(1));
        c.f_array(Arrays.asList("1"));
        c.f();
        c = new Child();
        c.f_array(Arrays.asList(1));
        c.f_array(Arrays.asList("1"));
        c.f();
    }
}
0 голосов
/ 24 июня 2010

Для класса TestValid: функции кажутся перегруженными. Вы не получите ошибку времени компиляции, если вызывающая сторона передаст объект списка List, тип которого определен. так как подпись (возвращаемый тип и входные параметры) после стирания типа не совпадает. Однако вы получите ошибку времени компиляции, если вы передадите new ArrayList () .

Второе определение нарушает основной принцип перегрузки функции, когда две функции с одинаковой сигнатурой (тип возвращаемого значения и входные параметры) после стирания типа.

0 голосов
/ 24 июня 2010

После стирания типа в компиляции, List<String> и List<Integer> оба действительно являются типом List;в TestInvalid вы делаете два метода с одной и той же сигнатурой во время выполнения.

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