Java,泛型不起作用

标签 java generics

在我看来它应该有效,但它没有。为什么?源代码:

package javaapplication1;

import java.util.*;

class A
{
    public static <K,V> Map<K,V> map()
    {
        return new HashMap<K,V>();
    }
}

class Person {}
class Dog {}

public class JavaApplication1
{

    static void f(Map<Person, List<? extends Dog>> peopleDogList) {}

    public static void main(String[] args)
    {
        f(A.<Person, List<Dog>>map());
    }
}

非常简单的代码。编译器错误: 类 JavaApplication1 中的方法 f 不能应用于给定类型; 必填:Map<Person, List<? extends Dog> 找到:Map<Person, List<Dog>> 原因:实参Map<Person, List<Dog>>无法转换为 Map<Person, List<? extends Dog>通过方法调用转换。

Map<Person, List<? extends Dog>比较通用,那么编译器应该可以转换吧?

还有这个:Map<Person, List<? extends Dog>> peopleDogList = A.<Person, List<Dog>>map();不起作用。 ? extends Dog表示继承 Dog 的对象或 Dog , 所以字 Dog应该可以吧?

最佳答案

Map<Person, List<Dog>>Map<Person, List<? extends Dog>> 不兼容.在这种情况下, map 的值类型应为 List<? extends Dog> ,而不是可以转换为相同的东西。但是如果你使用 Map<Person, ? extends List<? extends Dog>>对于 f的参数,它将起作用。

这是一个涉及更多基本类型的简单示例:

Map<String, List<?>> foo = new HashMap<String, List<Object>>();         // error
Map<String, ? extends List<?>> foo = new HashMap<String, List<Object>>();  // ok

OP 询问为什么会出现这种行为。简单的答案是类型参数是不变的,而不是协变的。也就是说,给定一个类型 Map<String, List<?>> , map 的值类型必须完全 List<?> ,不是类似的东西。为什么?想象一下,如果允许协变类型:

Map<String, List<A>> foo = new HashMap<>();
Map<String, List<?>> bar = foo;   // Disallowed, but let's suppose it's allowed
List<B> baz = new ArrayList<>();
baz.add(new B());
bar.put("baz", baz);
foo.get("baz").get(0);            // Oops, this is actually a B, not an A

糟糕,对foo.get("baz").get(0)的期待成为A被侵犯了。

现在,假设我们以正确的方式进行操作:

Map<String, List<A>> foo = new HashMap<>();
Map<String, ? extends List<?>> bar = foo;
List<B> baz = new ArrayList<>();
baz.add(new B());
bar.put("baz", baz);              // Disallowed

在那里,编译器捕获了将不兼容列表放入 foo 的尝试。 (通过别名 bar )。这就是为什么 ? extends是必需的。

关于Java,泛型不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18346641/

相关文章:

c# - 从通用模型中获取模型

java - 可以计算 2 个区间之间的数字的最大平方根次数

java.lang.NullPointerException,尝试在 Android 应用程序上读取空对象引用上的字段

swift - 无法使用可编码通用参数调用函数

java - 有界扩展枚举参数的通用方法 - 无法访问 values() 方法

c# - 如何在一个界面中使用不同的模板参数两次使用相同的界面?

java - 如何使用netbeans 7开发需要netbeans平台6x的应用程序?

java - 为什么这个 SimpleDateFormat 不能解析这个日期字符串?

java - 我无法在 Windows 10 计算机中安装 Java

java - 原始类型、无界通配符和有界通配符