Puzzle 89: Generic drug

Source: Internet
Author: User

Like the previous puzzle, this puzzle also uses a lot of generics. We learned from the previous mistakes and will not use the native type this time. This program implements a simple linked list data structure. The main program constructs a list containing two elements, and then outputs its content. So what will this program print?

public class LinkedList<E> {    private Node<E> head = null;    private class Node<E> {        E value;        Node<E> next;        // Node constructor links the node as a new head        Node(E value) {            this.value = value;            this.next = head;            head = this;        }    }    public void add(E e) {        new Node<E>(e);        // Link node as new head    }    public void dump() {        for (Node<E> n = head; n != null; n = n.next)            System.out.println(n.value + " ");    }    public static void main(String[] args) {        LinkedList<String> list = new LinkedList<String>();        list.add("world");        list.add("Hello");        list.dump();    }}

It is also a seemingly simple program. The new element is added to the table header of the linked list, and the dump method also prints the list from the table header. Therefore, the print order of elements is the opposite of the order they are added to the linked list. In this example, the program first adds "world" and then "hello", so in general it seems to be a complicated Hello World Program. Unfortunately, if you try to compile it, you will find that it cannot be compiled. The error message of the compiler is completely incomprehensible:

LinkedList.java:11: incompatible typesfound : LinkedList<E>.Node<E>required: LinkedList<E>.Node<E>              this.next = head;                            ^LinkedList.java:12: incompatible typesfound : LinkedList<E>.Node<E>required: LinkedList<E>.Node<E>              head = this;                      ^

The compiler tries to tell us that this program is too complicated. The internal class of a generic class can access the type parameters of its peripheral class. The programmer's intention is obvious, that is, the type parameter of a node should be the same as the type parameter of its peripheral list class, so node does not need its own type parameter. To correct this program, you only need to remove the type parameters of the internal class:

// The repaired code can be modified better.

Public class shortlist <E> {private node head = NULL; private class node {e value; node next; // node constructor, link node to the linked list as the new header node (e value) {This. value = value; this. next = head; head = This ;}} public void add (E) {new node (E ); // link the node to the linked list as a new header} public void dump () {for (node n = head; n! = NULL; n = n. Next) system. Out. Print (N. Value + "");}}

The above is the simplest solution to solve the problem, but it is not the best. The internal classes used by the initial program are not required. As mentioned in puzzle 80, you should prioritize the use of static member classes instead of non-static member classes [EJ Item 18]. An instance of vertex list. node contains not only the value and next fields, but also a hidden field, which contains references to peripheral vertex list instances. Although an external class instance is used to read and modify the head during the construction phase, once the construction is complete, it becomes a burden that cannot be discarded. Worse, this makes it hard to understand the program by placing the modified head in the constructor. Modify the instance domain of the class only in the method of the class.

Therefore, a better solution is to move the head operation in the initial program to the lateral list. Add method, which will make node a static nested class instead of a real internal class. Static Nested classes cannot access the type parameters of their peripheral classes, so now node must have its own type parameters. The modified program is simple, clear, and correct:

class LinkedList<E> {    private Node<E> head = null;    private static class Node<T> {        T value; Node<T> next;        Node(T value, Node<T> next) {            this.value = value;            this.next = next;        }    }    public void add(E e) {        head = new Node<E>(e, head);    }    public void dump() {        for (Node<E> n = head; n != null; n = n.next)            System.out.print(n.value + " ");    }}

In short, the internal class of the generic class can access the type parameters of its peripheral class, which may obscure the program. Misunderstandings described in this puzzle are common for beginners of generic programmers. Setting an internal class in a generic class is not necessary but rarely used. You should consider refactoring your code to avoid this situation. When you nest another generic class in a generic class, it is best to set different names for their type parameters, even if the nested class is static. For Language designers, we may consider disabling the masking mechanism of type parameters. Similarly, the masking mechanism of local variables should also be disabled. Such rules can capture errors in this puzzle.

Puzzle 89: Generic drug

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.