重载:为什么List <string>和List <integer>会产生不明确的声明?

时间:2017-10-02 14:02:03

标签: java overloading ambiguity

为什么不编译? 我想知道根本原因。

如果

 List<String> 

的类型不同
 List<Integer> 

为什么

public String convert(List<String> strings) { return null; }

public String convert(List<Integer> strings) { return null; }

发表含糊不清的声明?

public class Converter {

    public void why() {
        List<String> strings = null;
        List<Integer> integers = null;

        strings = integers; // type mismatch
    }

    public String convert(List<String> strings) {
        // error: why is this ambiguous ?
        return null;
    }

    public String convert(List<Integer> strings) {
        // error: why is this ambiguous ?
        return null;
    }

}

4 个答案:

答案 0 :(得分:7)

泛型只是一种编译工具,可以使代码更强类型化 编译后,泛型确实被删除了。它被称为类型擦除 因此,List<Integer>List<String>在Java字节码中只变为List 并且您不能拥有多个具有相同签名的方法 而编译错误。
来自documentation

  

泛型被引入Java语言以提供更紧密的类型   在编译时检查并支持通用编程。至   实现泛型,Java编译器将类型擦除应用于

     
      
  • 将泛型类型中的所有类型参数替换为其边界或   对象,如果类型参数是无界的。生成的字节码,   因此,只包含普通的类,接口和方法。

  •   
  • 如有必要,插入类型转换以保护类型安全。

  •   
  • 生成桥接方法以保留扩展泛型中的多态性   类型。

  •   

答案 1 :(得分:4)

说明

不幸的是两个都是列表。 JDK / JVM不查看泛型类型,但它们看到采用相同对象类型(列表接口)的相同方法。

如果您看看@duffymo发布的link(在评论中) - 它解释了类型擦除的概念。引用:

类型删除

  
    

泛型被引入到Java语言中,以便在编译时提供更严格的类型检查并支持泛型编程。至     实现泛型,Java编译器将类型擦除应用于:

  
     
      
  1. 将泛型类型中的所有类型参数替换为其边界或   对象,如果类型参数是无界的。生成的字节码,   因此,只包含普通的类,接口和方法。

  2.   
  3. 如有必要,插入类型转换以保持类型安全。

  4.   
  5. 生成桥接方法以保留扩展泛型类型中的多态性。   类型擦除确保不为参数化创建新类   类型;因此,泛型不会产生运行时开销。
  6.   

答案 2 :(得分:1)

当Java在JDK 5.0中引入泛型时,生成的字节码没有改变(对于泛型)。较旧版本的Java没有泛型,因此列表之类的类没有元素类型信息。

基本上只有Java编译器会看到泛型,它会对编译时间进行额外的检查,并添加额外的代码来进行类型转换,而不必再进行类转换。

在生成的图像中,此信息将被删除,因此Java运行时不再可见。在运行时映像中,两者都只是List个实例,因此无法区分。

由于Java运行时的动态行为,代码不直接链接到方法(就像在非虚拟C ++方法中那样),而是描述要调用的方法签名和名称。由于类型擦除,签名将变得相同,因此Java运行时无法决定调用哪个方法。

答案 3 :(得分:0)

如果你这样做:

public class Converter {

public void why() {
    List<String> strings = null;
    List<Integer> integers = null;

    strings = integers; // type mismatch
}

public String convert1(List<String> strings) {
    // error: why is this ambiguous ?
    return null;
}

public String convert2(List<Integer> strings) {
    // error: why is this ambiguous ?
    return null;
}

}

用户泛型查找方法convert1convert2

Method[] methods = Converter.class.getMethods();

您会发现方法convert1convert2具有相同的声明参数java.util.List。因此,一旦编译,您将发现参数消失。