gpt4 book ai didi

java - 引用和复制对象、意外行为

转载 作者:行者123 更新时间:2023-12-01 18:51:13 25 4
gpt4 key购买 nike

我需要知道为什么会发生以下情况,在这段代码(最后两个 block )中,我期望完全相同的输出,但本地对象(仅是对列表中的对象的引用,对吧?)仍处于旧状态列表更新时的状态。我有一个错误,因为我的游戏代码中存在类似的复制过程(基于图 block ,对象交换位置,所以我想为什么不只是交换它们的引用......)

示例:

package game;

import java.util.ArrayList;


public class Tester {
private String s;
private Foo foo;

public Tester(String s, String f) {
this.s = s;
this.foo = new Foo(f);
}

class Foo {
private String f;

public Foo(String f) {
this.f = f;
}
}

@Override
public String toString() {
return foo.f + ":" + s;
}
public void swap(Tester other) {
String tempS = this.s;
Foo tempFoo = this.foo;

this.s = other.s;
this.foo = other.foo;
other.s = tempS;
other.foo = tempFoo;

}



public static void main(String[] args) {
ArrayList<Tester> test = new ArrayList<Tester>();
test.add(new Tester("First", "1"));
test.add(new Tester("Second", "2"));

System.out.println("After initializing list");
for (Tester t : test) {
System.out.println(t);
}

Tester first = test.get(0);
Tester second = test.get(1);
Tester tmp = first;

first = second;
second = tmp;

System.out.println("\nAfter temps");
System.out.println(first);
System.out.println(second);

System.out.println("\nList changed after temps?");
for (Tester t : test) {
System.out.println(t);
}

System.out.println("\nAfter swap");
first.swap(second);
System.out.println(first);
System.out.println(second);

System.out.println("\nList after swap");
for (Tester t : test) {
System.out.println(t);
}
}
}

输出:

After initializing list
1:First
2:Second

After temps
2:Second
1:First

List changed after temps?
1:First
2:Second

After swap
1:First
2:Second

List after swap
2:Second
1:First

我想我有点不清楚,我总是先打印然后再打印(对象),所以“交换后”应该看起来与“交换后列表”完全相同,交换本地对象后列表已更改,本地对象(同样,仅仅是对列表中的对象的引用?)还没有。

对答案中的评论:虽然我的困惑被清除并且问题得到解决,但我在问是否可以获取列表对对象的实际引用,以便当我指向它时对于其他内容,列表也会自动指向其他内容。在下面的示例中,Foo a 首先指向具有属性 A 的对象 Foo,但该引用是从 list.get() 获取的。现在,如果我将其指向 new Turtles(),列表仍将指向 Foo with Aenter image description here

我希望有一个“硬”引用,这样当我指向海龟时,数组列表就指向海龟。 enter image description here

这将使交换更容易,但我还不确定如何实现可以执行此操作的列表(如果可能的话),这将非常适合我的游戏的特定需求。

最佳答案

在处理对象时需要记住的是,保存对象的变量实际上并不代表该对象。变量的值是内存中指向对象存在位置的指针。

某种类型的对象的ArrayList,通过扩展,实际上并不保存对象。它保存对象引用,或指向内存中对象位置的指针。

当你说:

Object a = new Object();
Object b = new Object();
a = b;

您将a设置为指向b的指针的值;换句话说,由于 ab 都指向内存中的同一个对象,因此更改一个对象会更改另一个对象。

现在回答你的问题,记住这一点。如果您从 ArrayList 中取出两个对象引用,然后交换它们,那么您就交换了对对象的引用;但是,引用在 ArrayList 中的位置并未更改。这解释了前三个输出。

但是,一旦进行内部交换,您就更改了存储在每个对象中的值。这意味着,虽然指向第一个和第二个对象的指针在内存中仍然相同,但它们的内部信息已经交换了。

这解释了最后两个输出。

(请注意,这也是为什么您必须使用 System.arraycopy 而不是设置 int[] a 等于 int[] b 的原因>; 如果你选择后者,那么改变 a 就会改变 b。)

关于java - 引用和复制对象、意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15867213/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com