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

3

4

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>
Manama answered 15/6, 2011 at 16:34 Comment(3)
"I'm guessing there is no difference"--how do you mean? Didn't those posts explain the differences?Entropy
In the second example, SomeAbstract is a formal type parameter. It doesn't refer to the class by the same name. Are you sure this is what you meant?Pylorectomy
@Michael Brewer-Davis The posts i've read pertain to List specifically, and how one extend/super/specific are read-only/write-only/both respectively. I don't see how that pertains to if the type is not a list/coolection.Manama
D
8

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.

Distil answered 15/6, 2011 at 16:38 Comment(4)
Wowah. Lost me there. "no longer refers to the actual type SomeAbstract that the first example uses at all" ?Manama
In class My_Abstract<SomeAbstract>, the SomeAbstract does not refer to the class SomeAbstract, but is the name of the Type parameter. My_Abstract<SomeAbstract> and My_Abstract<T> are equivalent!Elaterid
Hmmm. Interesting. I thought it would throw an error if i gave the type name an identifier already assigned to another class. And when I typed XXX in the type the line showed an error, but that must have been unrelated. Thanks.Manama
It's not a compile error, but if you're using an IDE you will see a warning that says something like, "type parameter 'SomeAbstract' hides class of the same name"Pylorectomy
C
2

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;
Centurion answered 15/6, 2011 at 16:58 Comment(0)
K
0

Using extends in a generic class declaration:

  1. Restricts the types that can be used as parameter to those that descend from the extended class.
  2. Allows the generic class to invoke the methods declared in the extended class.

The '?' keyword is used in methods when the code at hand doesn't care about the specific type of the type parameter, but cares only about an lower (extends) or upper (super) bound on it.

Wikipedia explains the net effects of the different constructs in a very pragmatic way.

To understand why several different constructs are needed to specify generics, you'd have to read about covariance and contravariance, which are the theoretical names of the rules for static type safety in the presence of generics.

Katrinakatrine answered 16/6, 2011 at 12:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.