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

家住魔仙堡 提交于 2021-02-05 06:21:08

问题


See below simple snippet:

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));
}

This would cause an ambiguous method call and will not compile.

This is utterly confusing on the user of that class. It is not able to call neither print1(T t) nor print1(Integer i) simple because it unfortunately used Integer as the generic type.

I understand generics is compile-time and there is type erasure, but doesn't Java have something to prevent such errors?
What if the GenericsOverloadingDistinguish Class is given and can't be changed, and I just need to invoke print1(T t) with T being an Integer?


回答1:


If the class is given, you're out of luck, there are no nice ways to resolve the problem.

How would you guess which method the designer expected to be called in this case? You simply can't. Now think of how the compiler could do the job?

What could've been done in the language is to not allow this kind of overloading at all if the type parameter can be given a conflicting value. Why it hasn't been done is a good question but difficult to answer. It was probably deemed too restrictive.

Anyway, if you absolutely must, you can work around this problem like this:

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

This works, because the type erasure of print1(T) is print1(Object).

Needless to say, this is bug ugly, and you really shouldn't be using raw types, but this is the least messy way of dealing with a bad situation.




回答2:


You can actually avoid this by doing:

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));
}

If your code is as-is and cannot be changed, then you're in a problem, since there is no clean (imo) way to distinguish if T or Integer overloaded method should be called.



来源:https://stackoverflow.com/questions/35104399/overloading-a-method-which-takes-in-generic-type-causes-ambiguous-method-call-co

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!