如何使用变量创建对我的对象的引用?

How do I create a reference to my object using a variable?

所以我有一个充满节点的数组,名为“SNodes”(它们是我自己创建的 class。它们实际上只是一个包含单个字符串和一个字符串的基本节点指向下一个节点的指针)。

我有一个名为 insertValue() 的方法,它接收要放入值的索引和希望 SNode 包含的字符串。但是,如果传递的索引中已经包含 SNode,我希望新值成为 SNode 的“下一个”节点(实质上是在中创建 linked 节点列表每个索引 space).

private int insertValue(int arrayPos, String element){//Checks for collisions with another SNode, and inserts the SNode into the appropriate spot in the array
 SNode targetNode = array[arrayPos];//What I want to be a reference to the node at the desired position in the array

 while (targetNode != null){//If an SNode already exists in that position, keeps iterating down until it gets to a non-existant SNode.
  targetNode = targetNode.getNext();//getNext is a method in my SNode that just returns a reference to that SNode's "nextNode" variable.
 }
  targetNode = new SNode(element);
  return arrayPos;
}//end insertValue

我的问题是,在我 运行 这个方法之后,它不会在所需的数组位置创建一个新节点,即使是第一次 运行ning 当数组点为空时也是如此。

如果我将 targetNode = new SNode(element); 更改为 array[arrayPos] = new SNode(element); 它显然会将 SNode 插入到数组中就好了,所以这让我相信正在发生的是新的 SNode 是在变量 targetNode 下创建的,但是 targetNode 在实例化后没有被 link 编辑到数组位置。我假设它本质上是将数据从第 2 行的数组位置复制到变量中,但随后变成了它自己的独立实体。

那么我如何让 targetNode 实际引用并影响 SNode? (这样当我向下遍历已占用数组 linked 的节点列表时 space,targetNode 指向正确的节点。

注意: 为了简单起见,我省略了在 SNode 到 link 中使用 setNext() 方法的行linked 列表中的前一个节点到它的下一个节点。

这里targetNode指的是array[arrayPos]所引用的对象。

 SNode targetNode = array[arrayPos];//What I want to be a reference to the node at the desired position in the array

但是当你写的时候:

targetNode = targetNode.getNext();//getNext is a method in my SNode that just 

您更改了 targetNode 变量引用的对象。现在它指的是它的下一个节点。

然后当你这样做时:

 targetNode = new SNode(element);

您创建了一个新对象并将其分配给 targetNode 变量,但最终它从未关联到现有节点。

它不会为下一个节点分配一个新节点。
为此,您可以这样写:

targetNode.setNext(new SNode(element));

你误会了。变量和数组元素都不包含对象。他们持有对对象的 引用 。此外,变量和数组位置本身不是对象,因此 Java 中没有办法引用它们。您最接近的是拥有变量或数组位置包含的值的副本(对对象的引用)。

因此,这...

SNode targetNode = array[arrayPos];

... 将 array[arrayPos] 的值复制到变量 targetNode 中。如果该值是非 null,则之后的变量引用与数组元素相同的对象,但不复制对象本身。在这种情况下,这很好,而且正是您想要的,因为当您使用

遍历链表时
targetNode = targetNode.getNext();

,您不想修改 array[arrayPos] 或任何节点的 next 引用,因为那样您会丢失链表的元素。

但你不能两全其美。当您最终找到新 SNode 的位置并执行此操作时 ...

targetNode = new SNode(element);

... 它不会记录对新 SNode 的引用,无论您最近从何处复制 targetNode 的值。它只是将引用放在 targetNode.

你想要做的是找到最后一个当前节点,如果有的话,并分配给它的 next 引用(或者直接分配给数组元素,如果它最初是 null)。

如其他答案所示,使用正常的解决方案,您将测试它是否是数组中的第一个元素,并在这种情况下做一些不同的事情。即如果是第一个就直接在数组中设置元素,如果不是第一个就遍历链表。

一种有效的替代方法是在数组中使用虚拟元素,该元素仅用于其下一个字段,并在创建时使用虚拟元素初始化数组。在你的情况下,你甚至可以给虚拟元素一个额外的 last 字段,这将不需要遍历列表来找到最后一个元素。类似于以下内容:

interface SNodeRef {
    SNode getNext();
    void setNext(SNode node);
}

class FirstNode implements SNodeRef {
    SNodeRef getLast();
    void setLast(SNodeRef);
    ....
    FirstNode() { setLast(this); }
}

class SNode implements SNodeRef { ... }

private int insertValue(int arrayPos, String element) {
    SNode newNode = new SNode(element);
    FirstNodeRef ref = array[arrayPos];
    ref.getLast().setNext(newNode);
    ref.setLast(newNode);
}

FirstNode[] array = new FirstNode[10];
for (int i = 0; i < array.length; i++) {
    array[i] = new FirstNode();
}

或者,由于它是您正在使用的链表,您可以简单地使用预定义的 LinkedList 数据结构:

private int insertValue(int arrayPos, String element) {
    array[arrayPos].addLast(element);
}

var array = new LinkedList<String>[10];
for (int i = 0; i < array.length; i++) {
    array[i] = new LinkedList<String>();
}