为什么一个班级有效而另一个班级没有?

时间:2010-06-23 20:16:11

标签: java eclipse generics overloading

如您所见,具有非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 个答案:

答案 0 :(得分:7)

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 :(得分:1)

在第二种情况下,由于类型擦除,无法在运行时区分方法f

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

因此他们都有完全相同的签名。

答案 2 :(得分:0)

在编译的类型擦除部分之后,List<String>List<Integer>都是真正的类型列表;在TestInvalid中,您正在使用相同的运行时签名创建两个方法。

答案 3 :(得分:0)

对于TestValid类: 功能似乎过载。如果调用者传递一个类型为define的参数List对象,则不会出现编译时错误.eg: new ArrayList&lt; Integer&gt;() new ArrayList&lt; String&gt;()。 作为类型擦除后的签名(返回类型和输入参数)不相同。 但是,如果您传入 new ArrayList()

,则会出现编译时错误

第二个定义违反了重载函数的基本原则,其中两个函数在类型擦除后具有相同的签名(返回类型和输入参数)。

答案 4 :(得分:0)

不支持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();
    }
}