为啥我不能有两个带有 ArrayList 参数的方法?

Posted

技术标签:

【中文标题】为啥我不能有两个带有 ArrayList 参数的方法?【英文标题】:Why can't I have two methods with ArrayList parameters?为什么我不能有两个带有 ArrayList 参数的方法? 【发布时间】:2014-04-07 20:54:23 【问题描述】:

为什么我不能创建两个参数都是数组列表但数据类型不同的重载方法?

public class test 
  public static void main(String[] args)

    ArrayList<Integer> ints = new ArrayList<Integer>();
    ints.add(1);
    ints.add(2);
    ints.add(3);
    ints.add(4);
    ints.add(5);

    showFirst(ints);

    ArrayList<Double> dubs = new ArrayList<Double>();
    dubs.add(1.1);
    dubs.add(2.2);
    dubs.add(3.3);
    dubs.add(4.4);
    dubs.add(5.5);

    showFirst(dubs);
   

  public static void showFirst(ArrayList<Integer> a)
  
    System.out.println(a.remove(0));
  

  public static void showFirst(ArrayList<Double> a)
  
    System.out.println(a.remove(0));
  

我在 Eclipse 中,它用红色强调了导致代码的问题并给出了以下消息:Method showFirst(ArrayList&lt;Integer&gt;) has the same erasure showFirst(ArrayList&lt;E&gt;) as another method in type test

我可以让它工作的唯一方法是在showFirst(ArrayList&lt;Integer&gt; a 之后添加其他参数,例如, int b, int bshowFirst(ArrayList&lt;Double&gt; a 之后。

有什么方法可以让这段代码按照我的预期工作吗?如果没有,我想知道为什么会这样。

运行程序会产生以下错误信息:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
  The method showFirst(ArrayList<Integer>) in the type test is not applicable for the arguments (ArrayList<Double>)
at test.test.main(test.java:25)

编辑:

使用 or ,如果我想做一些需要数据类型的事情,例如:

public static int[] reverseInArray(ArrayList<Integer> a)
  
    int n = a.size();
    int[] b = new int[n];
    while(n > 0)
    
    b[n] = a.remove(0);
    n--;
    
    return b;
  

  public static double[] reverseInArray(ArrayList<Double> a)
  
    double n = a.size();
    double[] b = new int[n];
    while(I > 0)
    
    b[n] = a.remove(0);
    n--;
    
    return b;
  

【问题讨论】:

查看类型擦除。 【参考方案1】:

在运行时,由于type erasure,每个ArrayList&lt;Whatever&gt; 都将转换为ArrayList(原始)。所以,只需要一种方法接收List&lt;? extends Number&gt;

//renamed to show what the method really does
public static void removeFirst(List<? extends Number> a) 
    System.out.println(a.remove(0));

请注意,上面的方法仅适用于Lists(ArrayListLinkedListList 的其他实现),它声明了一个从Number 扩展的类。如果您想要/需要一种方法从 List 中删除包含任何类型的第一个元素,请改用 List&lt;?&gt;

public static void removeFirst(List<?> a) 
    System.out.println(a.remove(0));

请记住始终program to interfaces instead of specific class implementation。

【讨论】:

+1 事实上,List&lt;?&gt; 是最合适的。 @PaulBellora 答案已更新,反映了 List&lt;? extends Number&gt;List&lt;?&gt; 之间的区别。 +1 作为建议.. 方法的名称应该尽可能具有声明性..如果您调用方法showFirst 我希望该方法不会从列表中删除元素! 【参考方案2】:

泛型仅在编译时强制执行。在运行时 ArrayListArrayList

在这种特殊情况下,您可以结合使用这两种方法:

public static void showFirst(ArrayList<? extends Number> a)

    System.out.println(a.remove(0));

【讨论】:

【参考方案3】:

因为泛型在运行时被擦除。换句话说,您的代码不知道这两种方法是不同的。事实上,您还有另一个编译器错误,您没有告诉我们:

Method showFirst(ArrayList<Integer>) has the same erasure showFirst(ArrayList<E>) as another method in type Main

【讨论】:

【参考方案4】:

只有这个方法,因为泛型只在编译时可用,所以,你的两个方法都被编译成相同的签名。所以要调用哪个方法就很模糊了

public static void showFirst(ArrayList<? extends Number> a)

    System.out.println(a.remove(0));

【讨论】:

这没有回答问题。 -1 generics are available only in runtime, 根本不是真的.. 在编译时;) @Nachokk :已更正,这是一个错字。【参考方案5】:

...由于type erasure,您的泛型参数在运行时是未知的,因此您的覆盖方法共享一个模棱两可的签名。

【讨论】:

以上是关于为啥我不能有两个带有 ArrayList 参数的方法?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能用相同的参数类型组合两个不同的函数?

为啥 out 参数不能有默认值?

为啥我不能在我的 ArrayList<T> 上调用 Collections.sort()?

为啥我不能拥有带有此签名的 Q_PROPERTY?

我正在尝试为 ArrayList .hasNext 写一个条件。为啥我不能写如下? [复制]

为啥 Asp.net MVC 不能区分具有不同参数的两个动作?