Collecting Java with generics giving me inapplicable arguments

I have a FourByFourBoard class that extends GameBoard . I define the following fields:

 private Map<Integer,List<Key<? extends GameBoard>>> mGameTypeToKeysMap = new Hashtable<Integer,List<Key<? extends GameBoard>>>(); private List<Key<FourByFourBoard>> mFourByFourBoardKeys = new ArrayList<Key<FourByFourBoard>>(); 

In my constructor, I am trying to call:

 mGameTypeToKeysMap.put(Game.FOUR_BY_FOUR, mFourByFourBoardKeys); 

But I get this:

The put(Integer, List<Key<? extends GameBoard>>) method put(Integer, List<Key<? extends GameBoard>>) of type Map<Integer,List<Key<? extends GameBoard>>> Map<Integer,List<Key<? extends GameBoard>>> not applicable for Arguments (int, List<Key<FourByFourBoard>>)

I can use a different approach to do what I'm trying to do, but with a little stare at the code, I cannot understand why this is not working.

EDIT

This problem may be simpler than I thought:

If I try:

 Key<GameBoard> a = mFourByFourBoardKeys.get(0); 

I get:

Type mismatch: cannot convert from Key<FourByFourBoard> to Key<GameBoard>

Even:

 GameBoard someBoard = new FourByFourBoard(); 

It is legal. So this is still a general question, but the compilation was not important. And my head is still spinning a bit.

+4
source share
3 answers

A List<A extends B> and a List<B> do not match, since you can add only instances of A to the first list, and you can add instances of A and B to the second.

All of this is perfectly explained in the Java generics study guide, more specifically on page 4 (Generics and Subtyping section)

Edit

A small example illustrating this and closer to your code

 Map<Integer, List<List<? extends Number>>> a = new Hashtable<Integer,List<List<? extends Number>>>(); List<List<Double>> b = new ArrayList<List<Double>>(); a.put(0, b);//won't compile List<List<? extends Number>> c = new ArrayList<List<? extends Number>>( ); a.put( 1, c );//works perfectly 

The reason why this does not compile is explained in the PDF I am attached to and quote the corresponding part

Let's test our understanding of generics. Is the following code snippet legal?

 List<String> ls = new ArrayList<String>(); //1 List<Object> lo = ls; //2 

Line 1 is definitely legal. The more difficult part of the question is line 2. This is minimized to the question: it is a list of lines of a list of objects. Most people's instincts should answer: โ€œof course!โ€. Ok, take a look at the following few lines:

 lo.add(new Object()); // 3 String s = ls.get(0); // 4: attempts to assign an Object to a String 

I suggest going through this entire PDF file and taking a look at the (other) examples in this document.

+3
source

The problem is that generic types must match exactly. Try the following:

 private List<Key<? extends GameBoard>> mFourByFourBoardKeys = new ArrayList<Key<? extends GameBoard>>(); 

You can add instances of FourByFourBoard to the OK list, but the card will accept this list.

Note. I tested this using standard JDK classes with a similar pattern, so anyone can copy this code for themselves:

 Map<Integer, List<Comparable<? extends Number>>> map = new HashMap<Integer, List<Comparable<? extends Number>>>(); List<Comparable<? extends Number>> list = new ArrayList<Comparable<? extends Number>>(); list.add(new Long(0)); map.put(new Integer(1), list); 
+1
source

? means "a certain type that I do not know"; ? extends Foo ? extends Foo means "some certain type that I don't know, but which extends Foo."

FourByFourBoard is a specific type that extends GameBoard , but the compiler cannot know that it is the same specific type as that specified in the mGameTypeToKeysMap definition.

To illustrate, I think it would be allowed to write:

 mGameTypeToKeysMap = new Hashtable<Integer,List<Key<EightByEightBoard>>>(); 

At this point, your put attempt would be very wrong.

+1
source

Source: https://habr.com/ru/post/1389961/


All Articles