提问人:Guy 提问时间:5/31/2017 最后编辑:marc_sGuy 更新时间:12/21/2020 访问量:520
如何使用变量创建对对象的引用?
How do I create a reference to my object using a variable?
问:
所以我有一个充满节点的数组,称为“s”(它们是我自己创建的类。从字面上看,它们只是一个基本节点,其中包含一个 String 和一个指向下一个节点的指针)。SNode
我有一个名为的方法,它接受您要放入值的索引和您希望包含的 String。但是,如果传递的索引中已经包含一个,我希望新值成为该“下一个”节点(实质上是在每个索引空间中创建节点的链接列表)。insertValue()
SNode
SNode
SNode
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);
SNode
SNode
targetNode
targetNode
那么我如何实际参考和影响?(这样,当我向下遍历已经占用的数组空间中的节点链表时,targetNode 指向正确的节点。targetNode
SNode
)
注意:为了简单起见,我省略了使用该方法将链表中的前一个节点链接到下一个节点的行。setNext()
SNode
答:
这里指的是 引用的对象。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));
评论
targetNode == null
targetNode = new SNode(element);
targetNode
targetNode
array[arrayPos]
array[arrayPos]
targetNode
array[arrayPos]
array[arrayPos] = new SNode(element)
targetNode = array[arrayPos]
.getNext()
array[arrayPos]
你有一个误解。变量和数组元素都不保存对象。它们包含对对象的引用。此外,变量和数组位置本身不是对象,因此在 Java 中没有办法引用它们。最接近的方法是拥有变量或数组位置包含的值的副本(对对象的引用)。
因此,这...
SNode targetNode = array[arrayPos];
...将 的值复制到 变量 中。如果该值为 non-,则变量之后引用数组元素的同一对象,但不会复制对象本身。这很好,正是你在这种情况下想要的,因为当你用array[arrayPos]
targetNode
null
targetNode = targetNode.getNext();
,您不想修改或任何节点的引用,因为那样您将丢失链表的元素。array[arrayPos]
next
但你不能两全其美。当您最终找到新职位并执行此操作时......SNode
targetNode = new SNode(element);
...它不会记录对新值的引用,无论它在哪里,您最近从中复制了 的值。它只是将引用放在 中。SNode
targetNode
targetNode
您要做的是找到最后一个当前节点(如果有),并分配给其引用(如果最初是,则直接分配给数组元素)。next
null
评论
if
SNode.
targetNode
正如其他答案所示,使用正常解决方案,您将测试它是否是数组中的第一个元素,并在这种情况下执行一些不同的操作。也就是说,如果元素是第一个元素,则直接在数组中设置元素,如果不是,则遍历列表。
一种有效的替代方法是在数组中使用一个虚拟元素,该虚拟元素仅用于其下一个字段,并在创建时使用虚拟元素初始化数组。在你的例子中,你甚至可以给虚拟元素一个额外的字段,这样就不需要遍历列表来查找最后一个元素。如下所示: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>();
}
评论