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

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

提问人:Guy 提问时间:5/31/2017 最后编辑:marc_sGuy 更新时间:12/21/2020 访问量:520

问:

所以我有一个充满节点的数组,称为“s”(它们是我自己创建的类。从字面上看,它们只是一个基本节点,其中包含一个 String 和一个指向下一个节点的指针)。SNode

我有一个名为的方法,它接受您要放入值的索引和您希望包含的 String。但是,如果传递的索引中已经包含一个,我希望新值成为该“下一个”节点(实质上是在每个索引空间中创建节点的链接列表)。insertValue()SNodeSNodeSNode

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

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

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

那么我如何实际参考和影响?(这样,当我向下遍历已经占用的数组空间中的节点链表时,targetNode 指向正确的节点。targetNodeSNode)

注意:为了简单起见,我省略了使用该方法将链表中的前一个节点链接到下一个节点的行。setNext()SNode

Java 变量 传递引用

评论


答:

1赞 davidxxx 5/31/2017 #1

这里指的是 引用的对象。targetNodearray[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));

评论

0赞 Guy 5/31/2017
是的,但是即使数组点在此程序第一次运行时为空(因此它跳过了 while 循环,因为 )它也不会在那里放置新节点。但感谢您指出这可能会令人困惑,我将编辑这个问题。targetNode == null
0赞 davidxxx 5/31/2017
不客气。它不起作用的原因与我解释的原因相同:创建一个新对象并将其分配给变量。但这意味着变量不再引用。所以它对 没有影响。targetNode = new SNode(element);targetNodetargetNodearray[arrayPos]array[arrayPos]
0赞 Guy 5/31/2017
是的,这正是我的问题。那么我怎么有参考呢?targetNodearray[arrayPos]
1赞 davidxxx 5/31/2017
创建元素并将其添加到数组中:然后将其存储在变量中:array[arrayPos] = new SNode(element)targetNode = array[arrayPos]
0赞 Guy 5/31/2017
好的,这适用于第一次迭代。但是,如果以后有另一个项目试图添加到该索引中,我怎么知道使用该方法多少次?因为就所有程序所知,在第一个节点之后的链表中可能有一个、两个或十个节点。.getNext()array[arrayPos]
1赞 John Bollinger 5/31/2017 #2

你有一个误解。变量和数组元素都不保存对象。它们包含对对象的引用。此外,变量和数组位置本身不是对象,因此在 Java 中没有办法引用它们。最接近的方法是拥有变量或数组位置包含的值的副本(对对象的引用)。

因此,这...

SNode targetNode = array[arrayPos];

...将 的值复制到 变量 中。如果该值为 non-,则变量之后引用数组元素的同一对象,但不会复制对象本身。这很好,正是你在这种情况下想要的,因为当你用array[arrayPos]targetNodenull

targetNode = targetNode.getNext();

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

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

targetNode = new SNode(element);

...它不会记录对新值的引用,无论它在哪里,您最近从中复制了 的值。它只是将引用放在 中。SNodetargetNodetargetNode

您要做的是找到最后一个当前节点(如果有),并分配给其引用(如果最初是,则直接分配给数组元素)。nextnull

评论

0赞 Guy 5/31/2017
啊哈!好的,所以最初我需要一个语句来检查数组索引是否为空。如果是,我需要直接编辑数组索引以添加新的但是之后我可以使用它指向它后面的链表对象,它会正常工作。谢谢,这完美地解决了我的问题!ifSNode.targetNode
0赞 fishinear 12/20/2020
您可能还希望在创建时使用虚拟 SNodes 初始化数组,这样您就不需要一直检查它是否是第一个节点。查看您的其他代码,该虚拟节点实际上可能是一个子类,该子类还具有指向列表中当前最后一个元素的指针,因此您无需遍历列表即可找到最后一个元素。
1赞 fishinear 12/21/2020 #3

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

一种有效的替代方法是在数组中使用一个虚拟元素,该虚拟元素仅用于其下一个字段,并在创建时使用虚拟元素初始化数组。在你的例子中,你甚至可以给虚拟元素一个额外的字段,这样就不需要遍历列表来查找最后一个元素。如下所示: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>();
}