BrownBear2018
BrownBear2018

Reputation: 57

JAVA Type Parameter in Linked List

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

Answers (1)

rzwitserloot
rzwitserloot

Reputation: 103018

Any class definition that is:

  • Inside another class definition.
  • not marked 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

Related Questions