Java 重载采用泛型类型的方法会导致方法调用不明确的编译错误

Java 重载采用泛型类型的方法会导致方法调用不明确的编译错误,java,generics,compilation,compiler-errors,overloading,Java,Generics,Compilation,Compiler Errors,Overloading,请参见下面的简单片段: 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

请参见下面的简单片段:

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));
}
公共类泛型重载区分{
公共作废打印1(T){
系统输出打印项次(“t”);
}
公共void print1(整数i){
System.out.println(“整数”);
}
}
公共静态void main(字符串[]args){
新的GenericsOverloadingDistrict().print1(新的整数(1));
}
这将导致方法调用不明确,并且不会编译

这对该类的用户来说是完全混乱的。它既不能调用
print1(tt)
也不能调用
print1(Integer i)
simple,因为它不幸地使用了
Integer
作为泛型类型

我知道泛型是编译时的,并且存在类型擦除,但Java难道没有防止此类错误的方法吗?

如果
genericsOverloadingDistrict
类已给定且无法更改,我只需要调用
print1(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));
}
公共类泛型重载区分{
公共作废打印1(T){
if(t instanceof Integer)
System.out.println(“整数”);
else System.out.println(“t”);
}
}
公共静态void main(字符串[]args){
新的GenericsOverloadingDistrict().print1(新的整数(1));
}

如果您的代码保持原样并且无法更改,那么您就遇到了问题,因为没有干净的(imo)方法来区分是否应该调用
T
Integer
重载方法。

如果给定了类,那么您运气不好,没有好的方法来解决问题

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

如果可以给类型参数一个冲突的值,那么该语言可以做的就是不允许这种重载。为什么没有这样做是一个很好的问题,但很难回答。这可能被认为限制性太强了

无论如何,如果您必须这样做,您可以这样解决此问题:

GenericsOverloadingDistinguish<Integer> t = new GenericsOverloadingDistinguish<Integer>();
((GenericsOverloadingDistinguish)t).print1((Object)new Integer(1)); //prints "t"
((GenericsOverloadingDistinguish)t).print1(new Integer(1)); //prints "integer"
GenericsOverloadingDifference t=新的GenericsOverloadingDifference();
((GenericsOverloadingDistrict)t).print1((对象)新整数(1))//打印“t”
((GenericsOverloadingDistrict)t).print1(新整数(1))//打印“整数”
这是可行的,因为
print1(T)
的类型擦除是
print1(Object)


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

我想如果这样的类存在并且不可修改,那就是糟糕的设计。确实没有干净的方法,但有一个不太复杂的脏方法:)哈哈,当我看到你的答案时,我想“什么!”:请注意,如果两个方法具有相同的擦除类型,则该语言实际上不允许重载。例如,尝试将
print1(整数i)
转换为
print1(对象i)
。代码将不会编译。这确保了你不会被完全禁锢在一个角落里,你甚至不能使用最黑客的解决方案来访问你想要的方法(因为,如果
print1(Object i)
在该示例中编译了,你的铸造解决方案将无法区分这两种方法)。@Kröw确实,或者您也可以尝试将
替换为