【问题标题】:Duplicate Method while Method-Overloading方法重载时重复方法
【发布时间】:2013-05-04 19:08:36
【问题描述】:

以下代码给出编译错误,错误为“重复方法”

static int test(int i){
     return 1;
}

static String test(int i){
     return "abc";
}

这是预期的,因为两个重载方法具有相同的签名并且仅在返回类型上有所不同。

但以下代码编译正常,但会出现警告:

static int test1(List<Integer> l){
    return 1;
}

static String test1(List<String> l){
    return "abc";
}

因为,我们知道 Java 泛型适用于 Erasure,这意味着在字节码中,这两种方法具有完全相同的签名并且返回类型不同。

此外,令我惊讶的是,以下代码再次出现编译错误:

static int test1(List<Integer> l){
    return 1;
}

static String test1(List l){
    return "abc";
}

第二个代码如何在没有任何编译错误的情况下正常工作,尽管有重复的方法?

【问题讨论】:

  • 那是因为List listList&lt;Integer&gt; list是同一个接口,你可能想read aboutList&lt;E&gt;
  • @AzadOmer:在运行时因为擦除所有列表都是相同的。所以,即使是第二个也应该给出编译错误,除非它是设计时特性。
  • 您也可以阅读这个问题,实际上您的问题可能重复Click Here
  • @AzadOmer:根据您提供的链接,即使代码 sn-p 2 也不应该编译,因为在运行时它们是具有相同签名但返回类型不同的方法。

标签: java generics overloading type-erasure erasure


【解决方案1】:
  1. 如果参数相同,Java 无法确定使用哪一个。因此,它会引发重复方法错误。
  2. StringListIntegerList 不能直接转换,所以方法不同。没有错误。
  3. List of Integer 也可以用作普通的 List,因此如果提供 List of Integer -> 重复方法错误,Java 无法确定使用哪一个。

【讨论】:

  • @Point 2:它们仅在设计时不同,但在运行时它们由于擦除而相同。这提出了两个问题:1)重载只是设计时功能吗? IE。如果编译器能够在设计时解决它,则虚拟机不会运行。 2) Class 文件可以有两个签名相同的方法,只是返回类型不同吗?
【解决方案2】:

解析重载方法是在编译时完成的,而不是在运行时完成的,因此 Java 编译器会在您的第二个示例中知道两者之间的区别。在您的第三个示例中,问题在于 List&lt;Integer&gt; 也是 List,因此如果您传入 List&lt;Integer&gt;,它将不知道使用哪个。

【讨论】:

  • 这是否意味着类文件可以有两个签名完全相同的方法(在这种情况下,因为擦除),但仅在返回类型上有所不同?
  • @Abhinav 是的。在我的编译器上,有两个这样的方法会导致返回类型相同的错误和不同返回类型的警告
【解决方案3】:

第一个结果是预期的并且是正确的。

现在让我们谈谈第二

让我们尝试调用这些函数。

List<Integer> intList;
List<String> strList;
test1(intList)
test1(strList)

编译器会调用相应的方法。

现在第三次

List<Integer> intList;
List unknownList;
test1(intList);
test1(unknownList);

哇!!编译器现在应该调用哪个方法!!因为unknowList 可以是IntegersList。 希望对您有所帮助。

【讨论】:

    【解决方案4】:

    方法重载的基本更改: 参数必须不同。在您的情况下,两种方法 test 始终使用相同的参数。其次,返回类型可能会或可能不会改变。请尝试第一个示例。

    static int test(int i){
    return 1;
    }
    
    static String test(List l){
    return "abc";
    }
    

    您的第二个示例有效,因为两个 List&lt;String&gt;List&lt;Integer&gt; 是两个不同的参数。

    第三个示例失败,因为整数列表也可以用作列表。如果将整数列表作为参数传递,代码运行后,Java 将无法确定应该调用两个函数中的哪一个。

    【讨论】:

    • List&lt;String&gt;List&lt;Integer&gt; 仅在设计时是不同的参数。由于 Erasure,它们在运行时是相同的。
    猜你喜欢
    • 1970-01-01
    • 2010-09-30
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多