user1067698
user1067698

Reputation: 177

Java method generics understanding

I'm trying to figure out why I can't I use super in a generic method declaration? See the example below, it doesn't compile, but I'm not sure why.

public class A<E> {
    public <T extends A> void test1(T t) {   // Compiles fine
    }
    public <T super A> void test2(T t) {     // Compilation error??
    }
    public <T super A> <T> void test3(T t) { // Compilation error??
    }
}

class A {}
....

Upvotes: 0

Views: 170

Answers (2)

Edwin Dalorzo
Edwin Dalorzo

Reputation: 78579

There is a difference between type parameters and type arguments. The use of wildcards (super and extends) is for type arguments, that is, you declare them at the call site when you're actually defining the corresponding value of a type parameter. Alternatively, the keyword extends can be used for type parameter constraints.

Type Parameters vs Type Arguments

As such, in the definition class List<T>{}, T is called a type parameter. Whe you a declare a reference of type List, at the call site you are allowed to provide a type argument for T, which can be an invariant (i.e. List<String> jedis) or a wildcard with super or with extends (i.e. List<? extends Number> myNums, List<? super String> names).

Type Parameter Constraints

The keyword extends can also be used in a totally different purpose to declare constraints for a given type parameter. For instance, the declaration:

class List<T extends CharSequence>{}

The type parameter T is constrained. This would imply that whenever you declare a type argument for your type parameter T, it must be of type CharSequence or any of its subtypes.

As such List<String> would be valid declaration, but List<Integer> would not.

The use of the keyword super is not allowed in the declaration of type parameter constraints, probably because it does not make a lot of sense, in your declaration, what could be a valid type argument for T that is not A itself?

Upvotes: 2

newacct
newacct

Reputation: 122429

Think about it, if a method could have the signature

public <T super A> void test2(T t) {
}

then it could take any object as argument. Why? Because, for example, you can always infer T as Object (Object is a supertype of A), and any object is an instance of Object, so it works. So declaring it this way would be pretty redundant. You could just write

public void test2(Object t) {
}

for the same effect.

Upvotes: 2

Related Questions