PinkElephantsOnParade
PinkElephantsOnParade

Reputation: 6592

Calling Generic-Defined Method in a Non-Generic-Defined Class in Main

I have a class, GraphSearch, defined as such:

public class GraphSearch{
///code
}

In this class is the generics-parameterized method:

public static <T> int dsp(T start, Map<T, List<Pair<T, Integer>>> adjList, T goal) {
///code}

I have a main I do this setup and call the method as such:

GraphSearch g = new GraphSearch();
HashMap<String,ArrayList<Pair<String,Integer>>> k = new  HashMap<String, ArrayList<Pair<String, Integer>>>();
////various setup to fill my map with valid stuff
///Pair is a class I made in my package

Then in main is

System.out.println("dsp from A to E is" + g.dsp("a", k, "e"));

I get an error.

The method dsp(T, Map<T,List<Pair<T,Integer>>>, T) in the type GraphSearch is not applicable for the arguments (String, HashMap<String,ArrayList<Pair<String,Integer>>>, String)

Well, why not? Is an ArrayList not a List? Is a String not a Generic-acceptable type? Is a Hashmap not a Map?

What's going on?

Upvotes: 1

Views: 105

Answers (2)

yshavit
yshavit

Reputation: 43391

Because Map<T, ArrayList<...>> is not a subtype of Map<T, List<...>>. See this thread (among others) for why.

Your generic should be Map<T, ? extends List<Pair<T, Integer>>> if you want to support that use case.

Another alternative would be to change k to be of type Map<String,List<Pair<String,Integer>>> -- this is preferable even if you do use the ? extends syntax, as it lets you program to the interfaces and use polymorphism better. For instance, you won't have to change k if you later decide that the values should be LinkedLists instead of ArrayLists.

Upvotes: 3

rgettman
rgettman

Reputation: 178263

The problem here is subtle, but it's based in the fact that in Java generics, a Type<A> is not a Type<B>, even if A extends B. Here, A is ArrayList, and B is List.

You defined a HashMap<String,ArrayList<Pair<String,Integer>>>, but your method expects a Map<String,List<Pair<String,Integer>>>. Try defining k with List instead of ArrayList, and it should work:

HashMap<String,List<Pair<String,Integer>>> k =
    new HashMap<String, List<Pair<String, Integer>>>();

OR define your dsp method to work with ArrayList instead:

public static <T> int dsp(T start, Map<T, ArrayList<Pair<T, Integer>>> adjList, T goal) {

Additionally, even if it's allowed, you should access static methods such as dsp via an instance of the class. It's preferred to access it with the class name, for clarity:

// GraphSearch.dsp instead of g.dsp.
System.out.println("dsp from A to E is" + GraphSearch.dsp("a", k, "e"));

Upvotes: 3

Related Questions