Consider a class definition that starts with
class Pokemon extends Playable<Pokemon>
This is similar to the more common class Pokemon implements Comparable<Pokemon>
, which just imposes a total ordering on the Pokemons.
Although I have been seeing this and writing this for some time, I realized (after fielding a question) that from a theoretical standpoint at least, there could be a risk of an infinite loop in parsing if one is not careful.
Consider this:
Step 1: The compiler or classloader tries to parse (or load) Pokemon
, but sees it needs to parse Playable<.>
first.
Step 2: The compiler then realizes because Playable
is parameterized by Pokemon
, it needs to load or parse Pokemon
. Now we find ourselves going to Step 1, and a never-ending cycle is established.
In practice, we know this is not the case, because it works. So how is cycle broken? My theory is that at the end of Step 2, the compiler or classloader just stops and use a "reference" to Pokemon instead of pulling up the Pokemon source code. But I don't know enough about javac
or the Classloaders
to affirm this. Could anyone weigh in?
This is similar to a "loop" in this declaration:
class LinkedListNode {
private String data;
private LinkedListNode next;
...
}
In order to process private LinkedListNode next
field, all the compiler needs to know is that LinkedListNode
is a type. It does not need to have a complete type at this point, because type name provides enough information to declare the field.
Similarly, when you declare a generic class that refers to its own type as part of its inheritance structure, the compiler does not need a complete type to finish parsing the declaration.