重载采用通用类型的方法会导致模棱两可的方法调用编译错误
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) 区分是否应调用 T
或 Integer
重载方法的方法。
如果给出 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)
。
不用说,这是一个丑陋的错误,你真的不应该使用原始类型,但这是处理糟糕情况的最简单的方法。
见下面的简单片段:
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) 区分是否应调用 T
或 Integer
重载方法的方法。
如果给出 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)
。
不用说,这是一个丑陋的错误,你真的不应该使用原始类型,但这是处理糟糕情况的最简单的方法。