views:

85

answers:

2

I have a method that returns an instance of

Map<String, List<Foo>> x();

and another method that returns an instance of

Map<String, Collection<Foo>> y();

Now if I want to dynamically add one of this Maps in my field, how can I write the generics for it to work?

ie:

public class Bar {
    private Map<String, ? extends Collection<Foo>> myMap;

    public void initializer() {
       if(notImportant) myMap = x(); //OK
       else myMap = y(); // !OK (Need cast to (Map<String, ? extends Collection<Foo>>)
    } 
}

Now is it ok that I cast to the signature even though the y() is declared as being Collection?

If it is not ok to cast, can I somehow write this (Collection OR List) I mean, List is a Collection, so it should somehow be possible.

private Map<String, Collection<Foo> | List<Foo>>> myMap;
+3  A: 

I'm not sure what your problem is. This code (essentially your code) compiles just fine.

import java.util.*;
public class Generic {
    static class Foo {};
    static Map<String, List<Foo>> x() {
        return null;
    }
    static Map<String, Collection<Foo>> y() {
        return null;
    }
    static Map<String, ? extends Collection<Foo>> myMap;
    public static void main(String[] args) {
        myMap = x();
        myMap = y();
        myMap = new HashMap<String,SortedSet<Foo>>();
        for (Collection<Foo> value : myMap.values());
    }
}

You can NOT, however, do something like List<Integer|String>. Java generics type bounds just doesn't work like that.

polygenelubricants
Also compiled just fine with `javac 1.6.0_17`. As it should.
polygenelubricants
+4  A: 

The way you did it with ? extends Collection is fine. You can't have something like OR since if you did you wouldn't know what it is you're getting back if you do myMap.get("someString"); you can't do List|Collection someVariable = myMap.get("someString"), you have to choose one, and if you choose Collection it's the same as using ? extends, if you choose List, you'll end up in all sort of trouble if the object in the map is actually a Set (which is also a collection), not a list, and you try calling methods that only List has (like indexOf). As for the reason you need to use ? extends is because Map<String, List> does not extend Map<String, Collection> even though List extends Collection.

You should take note though, that using ? extends Collection will only let you get values from the map, since then it's sure that what you get is a Collection (or child of Collection), but if you try to put something in the map, you won't be able to (since myMap may be Map<String, Set>, but since you only see it as Map<String, ? extends Collection> you might try to put a List in it which wouldn't be ok)

Andrei Fierbinteanu
+1; see also http://stackoverflow.com/questions/2776975/how-can-i-add-to-list-extends-number-data-structures
polygenelubricants