Java 使用递归类定义生成第一个对象

Java 使用递归类定义生成第一个对象,java,list,class,generics,Java,List,Class,Generics,我在java中做了一点实验,偶然发现了这个问题 假设我有一个具有这种递归定义的类 public class Node<T> implements Iterable<T>{ public final T element; public final Node<T> next; public Node(T head, Node<T> tail) { this.element = head; thi

我在java中做了一点实验,偶然发现了这个问题

假设我有一个具有这种递归定义的类

public class Node<T> implements Iterable<T>{
    public final T element;
    public final Node<T> next;

    public Node(T head, Node<T> tail) {
        this.element = head;
        this.next = tail;
    }
// Contains few more methods and implementation of iteratable like add, remove etc
}
public类节点实现Iterable{
公共最终T元素;
公共最终节点下一步;
公共节点(T头、节点尾){
这个元素=头;
this.next=tail;
}
//包含更多的方法和可迭代的实现,如添加、删除等
}
现在,我将使用这个类作为另一个类中带有final关键字的字段。现在,如果一开始我将制作一个空列表,然后将其添加到列表中,我应该如何继续

简单一点

class NodeList <T>{
    private final Node<T> head;

    public NodeList(){
    }

    // Few more functions
}
类节点列表{
私有最终节点头;
公共节点列表(){
}
//没有更多的功能
}
如何使用NodeList类创建空列表,然后使用java参考中的add函数添加数据作为指向内存中对象的指针,该对象在内部可以以相同的方式指向另一个对象

让我们试着从视觉上理解它:

将对象obj添加到空链表时,指针头会发生什么变化

您必须从
head
中删除
final
关键字,因为每次添加新节点指向新节点时,它的引用都会发生更改

在下面的快照中,快照头是指向内存中第一个对象的引用,第一个对象包含另一个指向第二个对象的引用,依此类推

我该如何进行

  • 创建一个新节点
  • 新节点的
    next
    点到头部的
    next
  • 指向新节点的点
    head

  • 示例代码:

    class Node<T> {
        public final T element;
        public final Node<T> next;
    
        public Node(T head, Node<T> tail) {
            this.element = head;
            this.next = tail;
        }
    }
    
    class NodeList<T> {
        private Node<T> head;
    
        public void add(T value) {
            if (head != null) { 
                Node<T> node = new Node<T>(value, head); // create a new node 
                head = node;   // point `head` to new node 
            } else {
                // if head is null then assign it to head
                head = new Node<T>(value, null);
            }
        }
    }
    
    NodeList<String> nodeList = new NodeList<String>();
    nodeList.add("First");
    nodeList.add("Second");
    nodeList.add("Third");
    
    // print all nodes
    Node<String> node = nodeList.head;
    while (node != null) {
        System.out.println(node.element);
        node = node.next;
    }
    

    您不能在head属性上使用final关键字,因为它将强制您在实例化期间对其进行初始化:然后您应该将其初始化为null以表示空列表,并且不能向其追加元素。删除最后一个关键字,它在那里没有用处


    我甚至不相信在节点类中使用final。如果要在列表中间添加或删除元素,该怎么办?使用final会大大限制您可以在数据结构上执行的操作数量。

    这很好,但问题是我可以创建head节点吗。因为我使用final关键字,所以我不能使用默认构造函数。我希望我能使用默认构造函数,比如Node l=new Node();然后我将使用l.add(“一些随机对象”)添加项;为什么要使用
    final
    ?把它拿走。给我一些时间来分享代码。添加了示例代码。我希望它是不可变的。我遇到了这两个链接供我参考,可能丢失了(答案二)和(可能是C#,idk)您可以使它不使用final而变为不可变的。通常,一个不可变的集合返回自己执行的操作的副本,而不是在对象本身上执行。@ AyuSououBy可以使它不可变,但是您的链接列表不能在中间添加元素。事实上,您的列表只能从一开始就添加元素,这将使它成为堆栈的良好实现。@Ayushchoubey,如果在
    NodeList#head
    中声明
    final
    ,则无法在构造函数之外的列表中添加任何元素。您的问题可以归结为:如何在Java中使用
    final
    修饰符?
    Third
    Second
    First