Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generics incompatible types (no instance(s) of type variable(s) T exist)

Tags:

java

generics

That's basically my first touch with Java generic types and I can't figure out what is wrong with the following piece of code.

I have a helper class Helper with a static function inRange usng generic type that should return the list of objects from an input list that are in certain range around object at index index (I haven't tested it yet, it's not an issue here if it works correctly or not):

public class Helper {
public static <T> List<T> inRange(List<T> list, int index, int range) {
    List<T> res = new ArrayList<T>();
    int N = list.size();
    assert(index < N);
    if (N == 0)
        return res;
    int i, j;

    /* right range */
    i = (index + 1) % N;
    j = 0;
    while (i != index && j < range) {
        res.add(list.get(i));
        i = (i + 1) % N;
        j++;
    }

    /* left range */
    i = (N + index - 1) % N;
    j = 0;
    while (i != index && j < range && !res.contains(list.get(i))) {
        res.add(lista.get(i));
        i = (N + i - 1) % N;
        j++;
    }

    return res;
}
}

Then I want to use it in a class:

import java.util.ArrayList;

public class StrategyA extends StrategyB {
public Decision makeDecision(GameView gameView, Action action, View playerView) {
    int pos = gameView.activePlayersViews().indexOf(playerView);
    assert(pos != -1);

    ArrayList<View> inRange = Helper.inRange(gameView.activePlayersViews(), pos, 
            playerView.range());
    // todo ...
    return new Decision(Decision.KindOfDecision.DO_NOTHING, 0);

}
}

where gameView.activePlayersView() is of type ArrayList<View>.

Then from my IDE (IntelliJ IDEA) on the line calling inRange(..) I get

Error:(8, 56) java: incompatible types: no instance(s) of type variable(s) T exist so that java.util.List<T> conforms to java.util.ArrayList<View>

Even I change generic type T directly to View I still get this error

like image 250
micsza Avatar asked May 15 '17 10:05

micsza


5 Answers

ArrayList is an implementation of List interface.
So all ArrayList instances are List instances but all List instances are not necessarily ArrayList.

So when you call this method :

public static <T> List<T> inRange(List<T> list, int index, int range) {

you cannot assign its result to an ArrayList as you are doing :

ArrayList<View> inRange = Helper.inRange(...);

Go on to program by interface and use List in both sides :

List<View> inRange = Helper.inRange(...);
like image 159
davidxxx Avatar answered Sep 23 '22 14:09

davidxxx


Minimize your example like (using Integer of the templated List type):

class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        List<Integer> list = new ArrayList<Integer>();
        ArrayList<Integer> inRange = Helper.inRange(list, 0,1);
    }
}

class Helper {
    public static <T> List<T> inRange(List<T> list, int index, int range) {
        List<T> res = new ArrayList<T>();
        return res;
    }
}

Then even if you put template types out of the picture:

ArrayList inRange = Helper.inRange(list, 0,1);

public static List inRange(List list, int index, int range) { ... }

you see that while the helper static method returns a List, you are trying to assign it to an ArrayList, and that's your problem, as ArrayList is a concrete implementation of List, but you cannot assign a reference to a generic List to a concrete implementation of ArrayList

Just change to:

List<View> inRange = Helper.inRange(gameView.activePlayersViews(), pos, 
        playerView.range());

and you are good to go: https://ideone.com/MXZxqz

like image 39
guido Avatar answered Sep 26 '22 14:09

guido


It happens, because inRange() returns type List<T>. You can store result in reference with type List or any supertype.

Try to use this code:

List<View> inRange = Helper.inRange(gameView.activePlayersView(), pos, 
            playerView.range());
like image 45
Vladimir Parfenov Avatar answered Sep 23 '22 14:09

Vladimir Parfenov


Try to do:

List<View> inRange = Helper.inRange(gameView.activePlayersView(), pos, 
        playerView.range());

And check this:

res.add(lista.get(i));

there is no lista in this class

like image 20
Razikus Avatar answered Sep 27 '22 14:09

Razikus


You need to cast the type ArrayList to be List

ArrayList<View> inRange = Helper.inRange((List<View>) gameView.activePlayersViews(), pos, 
playerView.range());
like image 21
SalaryNotFound Avatar answered Sep 23 '22 14:09

SalaryNotFound