Frage

This is a Generator class that is supposed to fill up an ArrayList of elements.

I do not understand why I get an error message when I call list.add(i);

I also tried to parse int to < T > and call list.add( (T) i) but that didn't work either.

public class Generator<T> {

public ArrayList<T> GenerateList(Number n) {
    ArrayList<T> list = new ArrayList<>();

    for (int i = 0; i < (int) n; i++) {
        list.add(i); //Error on this line (No suitable method found for add(int))
    }

    return list;
}

}

War es hilfreich?

Lösung

The typing of T could be anything. Inside the class there is no way of knowing whether it's safe to put an Integer (int gets boxed here automatically) in the list or not. It's only safe to put a T in a List<T>.

There won't be a way to add a concrete object to a generic list. The list must have a concrete type that definitely accepts Integer like List<Object>, List<Number> or List<Integer>.

Note that declaring that <T extends Integer> will not let you add an Integer to the list either. Integer is final but in an imaginary made-up Java where it's not, we could declare a Generator<IntegerSubtype> which would proceed to add an Integer to a List<IntegerSubtype>. This might later result in an Integer getting casted to an IntegerSubtype so it's not allowed.

A simplified example of the last point is like this:

class ListHolder<T extends Object> {
    List<T> list = new ArrayList<>();

    ListHolder() {
        list.add(new Object());
    }
}

(And this serves to illustrate the rest as well since an unbounded type parameter would normally have Object as an upper limit.)

T is bounded but it's more obvious that the list may very well not be able to hold Object. Actually since Object has no superclass, an Object can't be put in anything except a List<Object>. By putting an Object in the list we might be (and probably are) later going to end up incorrectly downcasting it in to a subtype.

If we supply a concrete type to a list, from the outside this same add just looks like this:

List<String> list = new ArrayList<>();
list.add(new Object()); // Object would be casted to String

It's the same thing for Integer, this is just implausible:

List<IntegerSubtype> list = new ArrayList<>();
list.add(new Integer(3)); // Integer would be casted to IntegerSubtype

(I say just 'implausible' because I'm thinking it might be possible to spoof a subtype of a final class using sun.misc.Unsafe...impossible in normal Java.)

Andere Tipps

You are attempting to an an integer (i)--specifically the index of the for loop--to an ArrayList<T>. A list of T is not a list of ints, hence the compiler is not allowing you to do this.

You need to do something like this:

list.add(someTObject);

The only way to make an integer work is to declare T as Number:

And since you are passing a Number into GenerateList (which is a function and really should be lowercase: generateList), I suspect you perhaps want this to be

public class Generator<N extends Number> {

   public ArrayList<N> GenerateList(N n) {    //N, not Number
       ArrayList<N> list = new ArrayList<>();

       for (int i = 0; i < n.intValue(); i++) {  //Must be n.intValue()
           list.add(n);   //THIS WORKS FOR N
       }

       return list;
   }
}

and then in the using class, declare <N> as Integer:

Generator<Integer> intGen = new Generator<Integer>();
intGen.GenerateList(3);  

I'm not sure what the for-terminator should be now, but I can't imagine i < n.intValue() is right.

At the moment you try to use the Generic ArrayList, it does not know what kind of Object it is going to store.

I am not sure of your intentions, but you should either make the ArrayList of type integer. Or if you really want that method to be generic specify what super types it should be allowed.

The ArrayList named list has a generic type T so you cannot add an integer item to it because the add method is expecting the type T or anything that extends it

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top