tags:

views:

121

answers:

2

I want to define the following class as such:

public class CollectionAttribute<E extends Collection<T>> {
    private String name;
    private E value;
    public CollectionAttribute(String name, E value) {
        this.name = name;
        this.value = value;
    }

    public E getValue() { return value; }

    public void addValue(T value) { value.add(T); }
}

This won't compile (cannot resolve symbol T). If I replace the class declaration with the following:

public class CollectionAttribute<E extends Collection<?>>

Then I can't reference the parametrized type of the collection.

Am I missing something or have I reached a limitation with generics in Java ?

+11  A: 

You need to add a second generic parameter for T:

public class CollectionAttribute<T, E extends Collection<T>> {
    private String name;
    private E values;
    public CollectionAttribute(String name, E values) {
        this.name = name;
        this.values = values;
    }

    public E getValue() { return value; }

    public void addValue(T value) { values.add(value); }
}

As Nathan pointed out, you also can't write value.add(T).

SLaks
:-o Any short explanation why?
OscarRyz
@Support: Otherwise, there is no `T` type.
SLaks
Isn't this redundant ? Now I have to specify my T twice when I create this object :(
Two Shoes
Yes, it is redundant. However, this is no other alternative, unless you get rid of the `E` parameter and replace it everywhere with `Collection<T>`.
SLaks
+6  A: 

There are two problems with your example class. The first is that you need to declare what T means, which means it needs to be included in the Generics for the class, or be a real class type. In this case, you probably want

public class CollectionAttribute<T, E extends Collection<T>> 

The second problem, which you probably would have found if you'd gotten the compiler past the first is that your addValue method's body is trying to add the type T to the collection, rather than that value:

public void addValue(T value) { this.value.add(value); }
Nathan