user1589188
user1589188

Reputation: 5736

Parameterised method returning generic class member in java

Why is the following code not allowed?

class MyClass {
    List<? extends Something> list;
    <T extends Something> List<T> myFunc(T t) {
        list = new ArrayList<T>(); // ok
        list.add(t); // error
        return list; // error
    }
}

And how do you fix the code while maintaining the same? i.e. the class member list only accepts objects that is subclass of Something and the same for myFunc()?

Upvotes: 0

Views: 68

Answers (3)

cesaregb
cesaregb

Reputation: 765

I think the Generic <T> declaration can be done at class level.

This to my understanding is because the wildcard ? cannot be used as a type argument.

The wildcard is never used as a type argument for a generic method invocation, a generic class instance creation, or a supertype

So what I get is that Java will not know that <T extends Something> and the list that even when it has the context that extends the same, it cannot ensure that is of the same type.

A possible (probably not what you are looking for) solution will declare the Generic at class level.

It may work if we do a:

class Abc <T extends Something>{
    List<T> list;
    List<T> myFunc(T t) {
        list = new ArrayList<T>(); // ok
        list.add(t); 
        return list; 
    }
}

I hope it helps.

Upvotes: 2

newacct
newacct

Reputation: 122439

You can't do list.add(t); because list has type List<? extends Something> and t has type T, and there is no way to know whether T is a subtype of the unknown type that ? represents.

Similarly, you can't do return list; because list has type List<? extends Something> and the return type of the list is List<T> and there is no way to know whether List<? extends Something> is List<T>.

I think what you're thinking is that you put a List<T> into the variable, so you know it's a List<T> and you try to use it like a List<T>. But that's not how it works. list has type List<? extends Something>. Whatever you may have put into it, that doesn't change the variable's type, and any uses of the variable must still be based on its compile-time type.

If you want to use the object that you created as a List<T> for things later in the method, you need to keep a variable of type List<T> to point to it, something like this:

<T extends Something> List<T> myFunc(T t) {
    List<T> tempList = new ArrayList<T>();
    list = tempList;
    tempList.add(t);
    return tempList;
}

Upvotes: 0

Jude Niroshan
Jude Niroshan

Reputation: 4460

You have to define your T type parameter somewhere before you use it anywhere. Ideally you should define it with the class declaration. Because you have used it in many places inside the class. If T would have only used in a method scope, you can define it with the method signature.

You cannot modify the Upper bounded <T extends Something> and Unbounded <?> type instances.

It means, it is not allowed to add any elements to List<?> (Unbounded list) and List<T extends Something>.

If you want to get this to be working, you can use a lower bound type parameter for the List.

class MyClass<T super Something> {
    List<T super Something> list;
    <T super Something> List<T> myFunc(T t) {
        list = new ArrayList<T>(); // ok
        list.add(t); 
        return list; 
    }
}

Upvotes: 0

Related Questions