Java,泛型不起作用

前端之家收集整理的这篇文章主要介绍了Java,泛型不起作用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在我看来它应该有效,但事实并非如此.为什么?源代码
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< Dog>>
原因:实际参数Map< Person,List< Dog>>无法转换为Map< Person,List<?延伸狗>通过方法调用转换.

地图<人员,名单<?延伸狗>更一般,所以编译器应该能够转换?

这也是:地图< Person,List<?延伸狗>> peopleDogList = A.< Person,List< Dog>> map();不起作用. ?延伸狗是指继承狗或狗的对象,所以单词Dog应该没问题?

解决方法

Map< Person,List< Dog>>与Map< Person,List<?不兼容延伸狗>>.在这种情况下,地图的值类型应为List<?扩展Dog>,而不是可转换为相同的东西.但如果您使用Map< Person,?扩展列表<?延伸狗>>对于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<?>>的类型,地图的值类型必须完全是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,? extends List<?>> bar = foo;
List<B> baz = new ArrayList<>();
baz.add(new B());
bar.put("baz",baz);              // Disallowed

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

猜你在找的Java相关文章