Java, generics don’t work

In my opinion, it should work, but that's not the case Why? Source code:

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());
    }
}

Very simple code Compilation error: method f in class javaapplication1 cannot be applied to the given type; Required: Map < personnel, list discovery: Map < person, list < dog > > reason: the actual parameter map < person, list < dog > > cannot be converted to map < person, list transform by method call

Map < personnel, list is more general, so the compiler should be able to convert?

This is also: Map < person, list > peopledoglist = A. < person, list < dog > > map(); It doesn't work? Extended dog refers to the object that inherits the dog or dog, so the word dog should be ok?

Solution

Map < person, list < dog > > and map < person, list > In this case, the value type of the map should be list instead of converting to the same thing But if you use map < person,? Extended list > it will work for the parameter of F

This is a simple example involving more basic types:

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

The op asked why this behavior occurred The simple answer is that type parameters are invariant, not covariant That is, given map < string, list > The value type of the map must be completely list , Not something like that Why? Imagine if covariant types are allowed:

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

Bad, expect foo get(“baz”). Get (0) becomes a is violated

Now, suppose we do this in the right way:

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

There, the compiler caught an attempt to put an incompatible list into foo (through the alias bar) Why? Extension is required

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>