2

I'm very confused facing this line of code:

public abstract class ClassName<T extends ClassName<?>>{}

I know what <T> is, what abstract is, what inheritance is but I just can't summarize all I see in this line.

Please can someone explain in simple words what does that interesting thing means? Not a duplicate of questions about <T> and <?>. The confusing thing here is that ClasName appears twice. Thanks in advance.

Simeon Leyzerzon
  • 18,658
  • 9
  • 54
  • 82
Evgeniy Mishustin
  • 3,343
  • 3
  • 42
  • 81

2 Answers2

4

public means the class is visible to all other classes.
abstract means the class can not be instantiated (you'll have to find a non-abstract subclass for that)
inheritance is an important concept in object-oriented programming. Read a book about OOP or consult wikipedia.

T extends ClassName<?> means there is an upper bound put on the type parameter T, such that T needs to be a subclass of ClassName<?>. ? means unbounded type parameter.

I will provide a little more meaningful example that might make it easier to understand the concept of using bounded recursive type parameters. Lets assume you have a class Thingy. You want all subclasses of Thingy to be comparable, but just to the same subclass. Ie you want nails to be comparable to nails, but not bikes:

interface Thingy<T extends Thingy<T>> extends Comparable<T> {}

class Nail implements Thingy<Nail> {
    @Override public int compareTo(Nail o) { ... }
}

class Bike implements Thingy<Bike> {
    @Override public int compareTo(Bike o) { ... }
}
Per Huss
  • 4,755
  • 12
  • 29
  • the confusing thing is how can abstract class be of type class that inherits from it? It sounds like neverending story – Evgeniy Mishustin Jun 16 '16 at 07:17
  • Not really. You just have to look at how a subclass may look... `class Foo extends ClassName{}` and `class Bar extends ClassName{}` could be two such subclasses... – Per Huss Jun 16 '16 at 07:20
  • @Evgeniy Mishustin That works through Type Erasure, important concept with generics. And yes, the neverending story is the cool thing about that, see my answer. Didn't even know about that possibility before :-D – GreenThor Jun 16 '16 at 07:21
  • *went learning "Type Erasure"* my lecturer missed that part )) – Evgeniy Mishustin Jun 16 '16 at 07:22
  • "You want all subclasses of Thingy to be comparable, but just to the same subclass." But the declaration doesn't do that. In fact, no declaration will do that in Java. You can still have `class Foo implements Thingy { @Override public int compareTo(Nail o) { ... } }` The recursive bound is useless in your example. – newacct Jun 21 '16 at 06:31
  • 1
    @GreenThor: Type erasure has *absolutely nothing* to do with it. – newacct Jun 21 '16 at 06:35
  • @newacct https://docs.oracle.com/javase/tutorial/java/generics/erasure.html As I see it, it does. Maybe I'm just getting the English wrong and maybe my memories of my lectures are a bit blurry, but I'm ready to learn if you can provide a resourceful reference. – GreenThor Jun 21 '16 at 12:25
  • @GreenThor: So, please tell what type erasure has to do with anything here. – newacct Jun 21 '16 at 23:51
3

So ClassName has a generic parameter T and this parameter needs to fit a certain requirement, in this case extends a certain type S, that means, T must inherit S. Now the interesting thing in this case is this S.

We have S to be ClassName<?>, so T must inherit from ClassName with a wildcard. For the wildcard aka the question mark please have a look at the link Michael Markidis gave in a comment to your question.

The real fun now is that this definition

public abstract class ClassName<T extends ClassName<?>>

allows recursive generic type defintion. So you could have something like

ClassName<ClassName<ClassName<ClassName<?>>>> test;

for whatever that's worth :)

EDIT: Given

ClassName2<T extends ClassName<?>> extends ClassName<T>

thats relatively easy in comparison. We want to inherit ClassName but not "destroy" the generic argument, so we take one ClassName would accept, in this case T extends ClassName<?>. In extends ClassName<T> the compiler checks if this (i.e. ClassName2's) T fits the T of ClassName, which was the requirement (remember ClassName's definition) T extends ClassName<?>, so this obviously works.

In addition, we have ClassName2<?> extending ClassName<?>, so now you can mix the two types however you want:

ClassName2<ClassName<ClassName<ClassName<?>>>> test2;
ClassName2<ClassName<ClassName2<ClassName<?>>>> test3;

However, if you would have, say

class ClassName3<T extends ClassName3<?>> extends ClassName<T>

(the public and abstrac modifiers don't really influence the generic behavior here), you can only have things like

ClassName3<ClassName3<ClassName3<ClassName3<?>>>> test4;
ClassName2<ClassName<ClassName3<ClassName3<?>>>> test5;

since ClassName and ClassName2don't inherit ClassName3.

GreenThor
  • 456
  • 5
  • 14
  • oh, I was afraid to hear the "recursive" in this context ))) Actually next class I have public abstract class ClassName2> extends ClassName. – Evgeniy Mishustin Jun 16 '16 at 07:21
  • @Evgeniy Mishustin extended my answer according to your comment :-) I'm glad the Type Erasure hint could help you – GreenThor Jun 16 '16 at 07:38