方法重载尝试给出名称冲突错误。不使用泛型

Method overload attempt gives name clash error. Not using Generics

我有以下代码。

public class myClass {

    public static void myMethod(
            ArrayList<ArrayList<Integer>> src,
            ArrayList<ArrayList<Integer>> dest,
            Integer[] selectedIndices) {

    }

    public static void myMethod(
            ArrayList<ArrayList<Double>> src,
            ArrayList<ArrayList<Double>> dest,
            Integer[] selectedIndices) {

    }
}

我期待 myMethod 的重载,但编译器抱怨 name clash 错误。在搜索 SO 时,我找到了一个相关的(可能不确定)答案 , but I am not using Generics. So my methods don't go through the type-Erasure。有人可以解释我错过了什么吗?

当你这样做时ArrayList<ArrayList<Integer>> src 你肯定在使用泛型。由于 type erasure

  • Integer 信息将丢失,即所有通用信息都将丢失
  • ArrayList<ArrayList<Integer>> srcArrayList<ArrayList<Double>> src 是一样的。
  • 因此,您定义的两个方法的方法签名将相同,不符合重载条件。

要解决这个问题,您可以如下声明您的方法并阅读 generics wildcard operator

ArrayList<ArrayList< ? extends Number>> src

在这里,NumberIntegerDouble 的超级 class。所以你的 class 将如下所示

public class MyClass {

    public static void myMethod(
            ArrayList<ArrayList<? extends Number>> src,
            ArrayList<ArrayList<? extends Number>> dest,
            Integer[] selectedIndices) {
    }
}

您可以将 ArrayList<ArrayList<Integer>>ArrayList<ArrayList<Double>> 传递给它。

您在这里遗漏了一个重点。 您仍在代码中使用泛型。

考虑这 2 个 LOC

  1. ArrayList<ArrayList<Integer>> src
  2. ArrayList<ArrayList<Double>> src

Java 在内部,在这些集合的实现中 classes 仅使用泛型来处理这两种情况,因此您面临 Type Erasure 问题。


编辑

看看这个ArrayListclass
(一般在C:\Program Files\Java\jdk1.7.0_45\src.zip\java\util\ArrayList.java)

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    ...
    ...
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }
    ...
    ...

如您所见,内部结构如您所料使用了泛型。

您肯定在使用泛型,并且正在进行类型擦除。你冷做以下

import java.util.ArrayList;

public class Test {

    public static <T> void myMethod(
        ArrayList<ArrayList<T>> src,
        ArrayList<ArrayList<T>> dest,
        Integer[] selectedIndices) {

    }
}

编辑 1: 在评论中回答你的问题。它从传入的参数派生类型。下面是一个关于如何使用它的示例。我还添加了一行,这将导致编译器失败,因为它们的参数类型不匹配。

import java.math.BigDecimal;
import java.util.ArrayList;

public class Test {
    public static <T> void myMethod(
        ArrayList<ArrayList<T>> src,
        ArrayList<ArrayList<T>> dest,
        Integer[] selectedIndices) {}

    public static void main(String[] args) {
        ArrayList<ArrayList<Integer>> srcInteger = null;
        ArrayList<ArrayList<BigDecimal>> srcBigDecimal = null;
        Integer[] indexes = null;

        myMethod(srcInteger, srcInteger, indexes);
        myMethod(srcBigDecimal, srcBigDecimal, indexes);
        myMethod(srcInteger, srcBigDecimal, indexes); // <- this will not compile
    }
}