Reputation: 5736
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
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
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
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