Reputation: 57
Java type parameter declaration as a part of inner class.
The question I have is on linked list. I am seeing the same thing in ArrayList
implementation.
public class LinkedList<E> implements Iterable<E> {....
private class LinkedIterator implements Iterator<E>{...} //inner class of LinkedList
private static class ListNode<E> //implemented as nested static class
Question: Why does the iterator (and constructor for LinkedList) both do not require type parameter, I think listNode requires because static class make it can not access class header of the outter class.
Upvotes: 1
Views: 395
Reputation: 103018
Any class definition that is:
static
is an inner class. Conceptually, the class exists only within a single instance of the outer class. Effectively, it means this:
There is a hidden, private, and final field of the outer type. All constructors require an instance of outer, but java syntax is special to pass it: outerRef.new Inner();
- and if you are in a context where Outer.this
would be sensible, that is the default value. This field does not have a getter.
All type params of the outer class are also available in the inner class unless shadowed.
So, given that private class LinkedIterator
is inside class LinkedList
, it is this kind of inner class, it has that hidden field, and it inherits the <E>
from LinkedList<E>
. The Node, however, is static
, therefore it does not have that field and does not inherit the <E>
- instead choosing to declare it itself.
Note that inner classes are complicated and surprising. They can for example mess up garbage collecting (because they hold a reference to their outer; that will prevent gc of the outer, for example). As a general rule, if you're not sure, strongly prefer static inner classes, making any inheritance of either an instance of outer or its generics explicit.
In other words:
public class Outer<E> {
public class Inner {}
}
is tricky; don't do that unless you're sure the concept of being an inner class fully applies. If you don't know what that means or aren't sure, write this instead:
public class Outer<E> {
public static class Inner<E> {
private final Outer<E> context;
public Inner(Outer<E> context) {
this.context = context;
}
}
}
omitting all parts you don't need, of course.
Upvotes: 2