将整数列表分配到字符串列表中

2022-09-01 05:14:08

我正在学习Java的泛型,我接近了一段非常有趣的代码。我知道在Java中,将一种类型的列表添加到另一种类型中是非法的。

List<Integer> integerList = new ArrayList<Integer>();
List<String> stringList=integerList;

所以在第二行中,我得到了一个编译时错误。
但是,如果我在这样的类中创建一个泛型方法,

class  GenericClass <E>{
    void genericFunction(List<String> stringList) {
        stringList.add("foo");
    }
    // some other code
}

在主类调用具有整数列表的方法时,我没有收到任何错误。

public class Main {
  public static void main(String args[]) {

     GenericClass genericClass=new GenericClass();
     List<Integer> integerList= new ArrayList<Integer>();
     integerList.add(100);
     genericClass.genericFunction(integerList);
     System.out.println(integerList.get(0));
     System.out.println(integerList.get(1));
  }
}

输出
100
foo

为什么我没有得到任何错误?


答案 1

您不会收到任何编译时错误,因为通过以原始方式使用:GenericClass<E>

GenericClass genericClass = new GenericClass();,

您实际上是在告诉编译器禁用泛型类型检查,因为您不在乎。

所以:

void genericFunction(List<String> stringList)

成为

void genericFunction(List stringList)用于编译器。

你可以尝试以下方法:,你会立即注意到编译器意识到泛型的不良使用,它会向你显示错误:GenericClass<?> genericClass

The method genericFunction(List<String>) in the type GenericClass<capture#1-of ?> is not applicable for the arguments (List<Integer>)

此外,如果您尝试在运行时获取第二位置对象的类:

System.out.println(integerList.get(1).getClass());

,您将收到一个错误:。java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer


答案 2

您已将通用与原始类型混合在一起。它可以正常编译,但在运行时它可能会失败,因为泛型信息在运行时丢失。

应使用泛型在编译时跟踪此类 bug。

在“什么是原始类型,为什么我们不应该使用它?”中对此进行了更好的解释?


警告:类型安全:该方法属于原始类型。对泛型类型的引用应参数化。genericFunction(List)GenericClassGenericClass<E>

如果您有两个同名方法,并且具有不同的泛型类型 List,则会导致编译时错误。编译器无法解析泛型类型,如果方法参数可以通过下面的示例代码证明。

示例代码:(编译器错误 - 不是有效的重载方法)

void genericFunction(List<String> stringList){...}
void genericFunction(List<Integer> stringList){...}

进行一些更改,然后重试:

class  GenericClass <E>{
    void genericFunction(List<E> stringList) {
        ...
    }
    // some other code
}

...

GenericClass<String> genericClass=new GenericClass<String>(); // Genreric object
List<Integer> integerList= new ArrayList<Integer>();
integerList.add(100);
genericClass.genericFunction(integerList); // compile time error

以这种方式创建方法

class GenericClass<E> {
    private List<E> list = new ArrayList<E>();

    public void addAll(List<E> newList) {
        list.addAll(newList);
    }

    public void add(E e) {
        list.add(e);
    }

    public E get(int index) {
        return list.get(index);
    }
    // some other code
}

推荐