【问题标题】:Overloading a method which takes in Generic type causes ambiguous method call compile error重载采用通用类型的方法会导致不明确的方法调用编译错误
【发布时间】:2016-05-08 08:40:43
【问题描述】:

看下面的简单sn-p:

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

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

这让该类的用户完全困惑。它既不能调用print1(T t) 也不能调用print1(Integer i) simple,因为不幸的是它使用了Integer 作为泛型类型。

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

【问题讨论】:

  • 我猜如果这样的类存在并且不可修改,那么它就是糟糕的设计。

标签: java generics compilation compiler-errors overloading


【解决方案1】:

如果给你上课,那你就不走运了,没有很好的方法来解决问题。

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

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

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

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)

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

【讨论】:

  • 在相关说明中,该语言实际上不允许在两个方法具有相同 erased 类型的情况下进行重载。例如,尝试将print1(Integer i) 变为print1(Object i)。代码不会编译。这可以确保您不会完全被困在一个角落,您甚至无法使用最骇人听闻的解决方案来访问您想要的方法,(因为,如果 print1(Object i) 在该示例中编译,您的铸造解决方案不会能够区分这两种方法)。
  • @Kröw 确实如此,或者您也可以尝试将&lt;T&gt; 替换为&lt;T extends Integer&gt;
【解决方案2】:

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

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) 方法来区分 if @应该调用987654322@或Integer重载方法。

【讨论】:

  • 确实没有干净的方法,但是有一个不太复杂的脏方法:)
  • 哈哈,当我看到你的回答时,我就像“什么!” :D
猜你喜欢
  • 2019-06-22
  • 1970-01-01
  • 2016-06-14
  • 1970-01-01
  • 1970-01-01
  • 2014-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多