无法理解构造函数以及在另一个 class 中调用它们的原因

Trouble understanding constructors and reasons for calling them in another class

我在大学学习软件工程,我通常对面向对象编程的基本概念有相当牢固的掌握,但最近我发现自己在一些不是的概念上落后了简单易懂。

一个主要问题是我无法理解 class 构造函数;如果我不尽快将其消灭在萌芽状态,我知道这将是我的垮台。

我已经请我的导师解释了,但一定是他们解释的方式导致我没有像往常一样的 "ah-hah" 时刻。

为了帮助你帮助我,请看下面的例子,工作程序(演示链表的使用和操作):

主要class:

package root;

public class Node<E> {
    private E nodeValue;
    private Node<E> next;

    public static void main (String[] args) {
        try {
            // Example 1: Create an empty list and print it. 
            SinglyLinkedList<Integer> list1 = new SinglyLinkedList<Integer>();
            System.out.println("Example 1: Create an empty list.");
            System.out.println(list1.printList());

            // ----------------------------------------------------------
            // Example 2: Create a list of 1 integer (1) using InsertNodeToTail.  
            System.out.println("\nExample 2: Create a list of 1 integer using InsertNodeToTail.");
            SinglyLinkedList<Integer> list2 = new SinglyLinkedList<Integer>();
            System.out.println("Before: " + list2.printList());
            list2.insertNodeToTail(1);
            System.out.println("After:  " + list2.printList());

            // ----------------------------------------------------------
            // Example 3: Create a list of 1 integer (1) using InsertNodeToHead.  
            System.out.println("\nExample 3: Create a list of 1 integer using InsertNodeToHead.");
            SinglyLinkedList list3 = new SinglyLinkedList();
            System.out.println("Before: " + list3.printList());
            list3.insertNodeToHead(1);
            System.out.println("After:  " + list3.printList());

            // ----------------------------------------------------------
            // Example 4: Create a list of 5 integers (1, 3, 5, 7, and 9) 
            // using InsertNodeToTail. Output: 1->3->5->7->9
            System.out.println("\nExample 4: Create list 1->3->5->7->9 using InsertNodeToTail.");
            // Create an array of 5 integers
            int[] array4 = { 1, 3, 5, 7, 9 };
            // Create the head node 
             SinglyLinkedList<Integer> list4 = new SinglyLinkedList<Integer>();
            System.out.println("Before: " + list4.printList());
            // Insert nodes
            for (int i = 0; i < array4.length; i++)
                list4.insertNodeToTail(array4[i]);
            System.out.println("After:  " + list4.printList());

            // ----------------------------------------------------------
            // Example 5: Create a list of 5 integers (1, 3, 5, 7, and 9) 
            // using InsertNodeToHead. Output: 1->3->5->7->9
            System.out.println("\nExample 5: Create list 1->3->5->7->9 using InsertNodeToHead.");
            // Create an array of 5 integers
            int[] array5 = { 1, 3, 5, 7, 9 };
            // Create the head node 
             SinglyLinkedList<Integer> list5 = new SinglyLinkedList<Integer>();
            System.out.println("Before: " + list5.printList());
            // Insert nodes
            for (int i = array5.length - 1; i >= 0; i--)
                list5.insertNodeToHead(array5[i]);
            System.out.println("After:  " + list5.printList());

            // ----------------------------------------------------------
            // Example 6: Insert new node before a current node
             System.out.println("\nExample 6: Insert node 0 before node 1.");
            // Use list2, insert node 0 before node 1
            System.out.println("Before: " + list2.printList());
            list2.insertNodeBefore(0, 1);
            System.out.println("After:  " + list2.printList());

            // ----------------------------------------------------------
            // Example 7: Insert new node before a current node
            System.out.println("\nExample 7: Insert node 4 before node 5.");
            // Use list4, insert node 4 before node 5
            System.out.println("Before: " + list4.printList());
            list4.insertNodeBefore(4, 5);
            System.out.println("After:  " + list4.printList());

            // ----------------------------------------------------------
            // Example 8: Insert new node after a current node
            System.out.println("\nExample 8: Insert node 2 after node 1.");
            // Use list2, insert node 2 after node 1
            System.out.println("Before: " + list2.printList());
            list2.insertNodeAfter(2, 1);
            System.out.println("After:  " + list2.printList());

            // ----------------------------------------------------------
            // Example 9: Insert new node after a current node
            System.out.println("\nExample 9: Insert node 10 after node 9.");
            // Use list4, insert node 10 after node 9
            System.out.println("Before: " + list4.printList());
            list4.insertNodeAfter(10, 9);
            System.out.println("After:  " + list4.printList());

            // ----------------------------------------------------------
            // Example 10: Remove node if node value is given
            System.out.println("\nExample 10: Remove node 10.");
            // Use list4, remove node 10
            System.out.println("Before: " + list4.printList());
            list4.remove(10);
            System.out.println("After:  " + list4.printList());

            // ----------------------------------------------------------
            // Example 11: Remove node that is not in the list
            System.out.println("\nExample 11: Remove node 100.");
            // Use list4, remove node 100
            System.out.println("Before: " + list4.printList());
            list4.remove(100);
            System.out.println("After:  " + list4.printList());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public Node() { 

    }

    public Node(E nVal) { 
        nodeValue = nVal; 
    }

    public Node(E nVal, Node<E> nextNode) {
        nodeValue = nVal;
        next = nextNode;
    }

    public E getNodeValue() {
        return nodeValue;
    }

    public void setNodeValue (E nVal) {
        nodeValue = nVal;
    }

    public Node<E> getNext() {
        return next;
    }

    public void setNext (Node<E> n) {
        next = n;
    }
}

子class:

package root;

import java.io.*;

public class SinglyLinkedList<E> {

    private Node<E> head;

    // Create an empty list 
    public SinglyLinkedList() {
        head = null;
    }

    // Access to the entire linked list (read only)
    public Node<E> getHead() {
        return head;
    }

    // Insert a node with node value = nVal as the last node
    public void insertNodeToTail(E nVal) {
        Node<E> lastNode = new Node<E>();
        lastNode.setNodeValue(nVal);
        if (head == null) {
            head = lastNode;
            return;
        }

        Node<E> curr = head;
        while (curr.getNext() != null) {
            curr = curr.getNext();
        }
        curr.setNext(lastNode);
    }

    // Insert a node with node value = nval as the first node
    public void insertNodeToHead(E nVal) {
        Node<E> newHead = new Node<E>();
        newHead.setNodeValue(nVal);
        newHead.setNext(head);
        head = newHead;
    }

    // Insert new node nVal to the list before current node curVal 
    public void insertNodeBefore(E nVal, E curVal) {
        Node<E> newNode = new Node<E>(nVal);

        Node<E> curr = head;
        Node<E> prev = null;

        if (head.getNodeValue() == curVal) {
            newNode.setNext(head);
            head = newNode;
            return;
        }

        // scan until locate node or come to end of list
        while (curr != null) {
            // have a match 
            if (curr.getNodeValue() == curVal) {
                // insert node
                newNode.setNext(curr);
                prev.setNext(newNode);
                break;
            } else {
                // advanced curr and prev
                prev = curr;
                curr = curr.getNext();
            }
        }
    }

    // Insert new node nVal to the list after current node curVal 
    public void insertNodeAfter(E nVal, E curVal) {
        Node<E> newNode = new Node<E>();
        newNode.setNodeValue(nVal);

        Node<E> curr = head.getNext();
        Node<E> prev = head;

        //scan until locate a node or come to the end of the list
        while (prev != null) {
            //have a match
            if (prev.getNodeValue().equals(curVal)) {
                //insert node
                newNode.setNext(curr);
                prev.setNext(newNode);
                break;
            } else {
                //advance curr and prev
                prev = curr;
                curr = curr.getNext();
            }
        }
    }

    // Remove the node containing item nVal
    public void remove(E nVal) throws IOException {
        if (head == null) {
            throw new IOException("List empty!");
        } else {

            Node<E> curr = head;
            Node<E> prev = null;

            // becomes true if we locate target
            boolean foundItem = false;
            // scan until locate nodeVal or come to end of list

            while (curr != null && !foundItem) {
                // have a match 
                if (curr.getNodeValue() == nVal) {
                    // if current node is the first node
                    // remove first node by moving head to next node
                    if (prev == null) {
                        head = head.getNext();
                    } else { // erase intermediate node
                        prev.setNext(curr.getNext());
                    }
                    foundItem = true;
                } else {
                    // advanced curr and prev
                    prev = curr;
                    curr = curr.getNext();
                }
            }
        }
    }

    public String printList() {
        String outputList = "";
        Node<E> temp = head;

        if (temp == null) {
            return "List empty!";
        }        
        do {
            // Print head node value
            outputList += temp.getNodeValue().toString();
            // Move to next node
            temp = temp.getNext();
            // if next node is not empty, print -> 
            // else print end of line then break the loop
            if (temp != null) {
                outputList += "->";
            } else {
                break;
            }
        } while (true);
            // the loop terminates itself when it reaches to 
            // end of the list
            return outputList;
    }
}

谁能解释一下泛型 Node<E>(主要)class 中构造函数的用途是什么? 在什么情况下应该调用它们?

如果你想创建一个新节点并且没有任何数据,你可以调用public Node() {

public Node(E nVal) {如果想创建一个有值的新节点可以调用

Node(E nVal, Node<E> nextNode) 被调用,如果你有 nodeValuenextNode

你有三个构造函数:

public Node() { 

}

public Node(E nVal) { 
    nodeValue = nVal; 
}

public Node(E nVal, Node<E> nextNode) {
    nodeValue = nVal;
    next = nextNode;
}

第一个是默认构造函数,不带任何参数。它实例化 Class 节点的对象。

第二个带参数(E nVal); nVal 是 E 类型,因此实例化的节点对象将是 Node 类型。

第三个构造函数有两个参数(E nVal, Node nextNode);它与第二个构造函数的作用相同,而且它设置了列表中的下一个节点 nextNode;然后,此引用存储在实例化对象的 next 变量中。

每个构造函数创建一个新的对象实例。默认构造函数不接受任何参数,如果您不提供任何您自己的代码,也不会对新对象执行任何操作。

为了方便起见,人们通常会在构造函数中使用代码创建带有参数 and/or 的构造函数,以便返回的新对象实例预先配置了一些数据。

例如,如果数据在构建后永远不会更改,这将特别有用。另一个用例是,您将获得的任何对象实例都遵守某些规则——您只能通过在构造函数中处理这些规则来安全地做到这一点,然后再提供对象实例以供使用。