java - 通用方法。多个参数匹配

标签 java generics

我不明白为什么这段代码可以正常工作。

static <T> int compare(T t1, T t2) {
    return 0;
}

public static void main(String[] args) {
    compare(new Thread(), new StringBuilder());
}

因为当我们遇到这样的事情时:

static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
    return;
}

public static void main(String[] args) {
    fromArrayToCollection(new Thread[] {}, new ArrayList<StringBuilder>()); // error
}

我们有一个错误。 为什么编译器不检查第一个例子中两个参数的匹配?抱歉提出愚蠢的问题。

最佳答案

泛型是不变的

泛型是不变,而不是协变

这意味着,虽然您可以这样做:

Dog dog = new Dog();
Animal animal = dog; // Dog works for Animal, classes are covariant

你不能这样做:

List<Dog> dogs = List.of(new Dog());
List<Animal> animals = dogs; // Error, generics are invariant

所以 List<Dog>类型List<Animal> .但是Dog类型为 Animal .

当然这是有道理的,因为animals会接受 Cat s,但是dogs不是。


解释

在您的第一个代码中,您没有指定要使用的类型,例如:

compare<Foo>(...)

所以你让编译器推导出类型。它搜索 Thread 的类型和 StringBuilder有共同点,即Object .

所以 T解析为 Object那里,很好:

static int compare(Object t1, Object t2) {
    return 0;
}

在你的第二个例子中它不能选择Object ,因为 Collection<Object>行为不同于 Collection<StringBuilder> ,因为泛型是不变的。因此无法找到匹配的类型,从而发生错误。

另见 Why are arrays covariant but generics are invariant? .

关于java - 通用方法。多个参数匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53123839/

相关文章:

java - Class 与 Class<?> 实例中的 getAnnotation()

swift - T.Type 和 [T.Type] 之间的不同行为

java - 如果不是独立构建,Maven war 包含额外的依赖项

java - LIBGDX - 标签与字体大小不匹配

java - 如何在 Canvas 上绘制 JPanel?

c++ - 会有标准类型列表吗?

java - 数据截断: incorrect data value : 'yyyy MMM d' for column 'date_acd' at row 1

java - struts中的文件上传

java 模板形式参数与 Void

c# - 为什么在传递命名方法时不能推断出这些类型参数?