Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between using <? extends SomeAbstract> vs. SomeAbstract in java generics

I'm moving over to java from DotNet and this idea of extends is new.

I've seen some posts that fully explain using List<? extends SomeAbstract> vs. List<? super SomeAbstract> vs. List<SomeAbstract>, but I'm guessing that there is no difference between using, and not using, extends in generics.

Is that true? Would the answer change if using an abstract class as the parent?

class My_AbstractExtends<T extends SomeAbstract>

vs.

class My_Abstract<SomeAbstract>

EDIT

Creates child classes as follows

class My_ChildExtends extends My_AbstractExtends<ConcreteChildOfSomeAbstract>

vs.

class My_Child extends My_Abstract<ConcreteChildOfSomeAbstract>
like image 778
rediVider Avatar asked Dec 28 '22 18:12

rediVider


2 Answers

I'm guessing you're talking about the use of extends in type parameter declarations. In that case:

class My_Abstract<T extends SomeAbstract>

has a bounded type parameter called T that must be SomeAbstract or some subtype of it.

class My_Abstract<SomeAbstract>

has an unbounded type parameter called SomeAbstract that could be anything. Note that SomeAbstract no longer refers to the actual type SomeAbstract that the first example uses at all!

To expand on that: imagine if the second declaration were class My_Abstract<T>. The T there is clearly a type parameter, not an actual type. But it doesn't have to be called T... it can be called E or Bob or SomeAbstract. In all of these cases, it is still just a type parameter... an actual type can never go there, nor does it make any sense for it to (the whole point of a type parameter is to NOT refer to a specific type but instead allow other types to be put in its place when instances of the class are created).

In the code you've edited in, change My_Child's declaration to

class My_Child extends My_Abstract<Object>

and you'll see the difference. If you actually try to do something using the type parameter SomeAbstract in the second version, you'd also find that you cannot call any methods declared in the real SomeAbstract class. This is all a good example of why you should always follow the convention of using single-letter type parameters... it's really confusing if you don't.

This is getting really long, but I also want to note that all of this is basically unrelated to the first half of your question. Wildcards like ? extends SomeAbstract and ? super SomeAbstract aren't used in type parameter declarations (such as those used when defining a generic class), they're primarily used for method parameters. List is a typical example for explaining why wildcards are needed because its nature as a container of objects makes it relatively easy to understand, but rules pertaining to them apply to any generic type. I tried to explain this in relatively general terms in this answer.

like image 176
ColinD Avatar answered Feb 01 '23 11:02

ColinD


It lets you refer to T in other places.

public class A<T extends SomeClass>{
    public A(T x){this.x=x;}
    public T x;
}

Then users of your class can use their original type instead of having to use SomeClass.

MyObject x = new A<MyObject>(new MyObject()).x;
like image 35
Jack Edmonds Avatar answered Feb 01 '23 12:02

Jack Edmonds