重载采用通用类型的方法会导致模棱两可的方法调用编译错误

Overloading a method which takes in Generic type causes ambiguous method call compile error

见下面的简单片段:

public class GenericsOverloadingDistinguish<T> {
    public void print1(T t) {
        System.out.println("t");
    }

    public void print1(Integer i) {
        System.out.println("integer");
    }
}
public static void main(String[] args) {
    new GenericsOverloadingDistinguish<Integer>().print1(new Integer(1));
}

这会导致模棱两可的方法调用,无法编译。

class 的用户非常困惑。它既不能调用 print1(T t) 也不能调用 print1(Integer i) 简单,因为不幸的是它使用 Integer 作为通用类型。

我知道泛型是编译时的,并且有类型擦除,但是 Java 没有办法防止此类错误吗?
如果给定了 GenericsOverloadingDistinguish Class 并且无法更改,我只需要调用 print1(T t) 并且 T 是一个整数怎么办?

您实际上可以通过以下方式避免这种情况:

public class GenericsOverloadingDistinguish<T> {
    public void print1(T t) {
        if (t instanceof Integer)
            System.out.println("integer");
        else System.out.println("t");
    }

}
public static void main(String[] args) {
    new GenericsOverloadingDistinguish<Integer>().print1(new Integer(1));
}

如果您的代码是原样并且无法更改,那么您就有问题了,因为没有clean (imo) 区分是否应调用 TInteger 重载方法的方法。

如果给出 class,那是你运气不好,没有很好的方法来解决这个问题。

在这种情况下,您如何猜测设计者希望调用哪个方法?你根本做不到。现在想想编译器是如何完成这项工作的?

如果可以为类型参数指定一个冲突值,则该语言本来可以做的就是完全不允许这种重载。为什么还没有完成是一个很好的问题,但很难回答。它可能被认为过于严格。

无论如何,如果你绝对必须,你可以像这样解决这个问题:

GenericsOverloadingDistinguish<Integer> t = new GenericsOverloadingDistinguish<Integer>();
((GenericsOverloadingDistinguish)t).print1((Object)new Integer(1)); //prints "t"
((GenericsOverloadingDistinguish)t).print1(new Integer(1)); //prints "integer"

这有效,因为 print1(T) 的类型擦除是 print1(Object)

不用说,这是一个丑陋的错误,你真的不应该使用原始类型,但这是处理糟糕情况的最简单的方法。