我目前正在学习Java游戏开发,并且正在尝试使用向量/点而不是基元来定位实体。在整个实验过程中,我发现了一些关于物体工作的方法,我不知道如何解决这些问题,请考虑这个例子。
Point p1 = new Point(0, 0);
Point p2 = p1;
p1.x++;
if (p1 == p2) System.out.println("these are the same");
更改了p1的坐标后,仍然处理了println,经过调试后我通过设置p2 = p1计算出p1发生的任何变化都将发送到p2。
最终我想知道为什么会这样。对象名称是否只是指向内存中某个位置的指针,这两个点都指向一个位置?
此外,还有办法吗?
答案 0 :(得分:1)
..对象名称是否只是指向内存中某个位置的指针,这两个点都指向一个位置?
是。真正。我们在Java中将其称为 reference
。 p2
指的是p1
。由于p2
不是new
对象且总是指向p1
,因此您对p1
所做的更改也可以通过p2
查看。< / p>
图片可以解释更多。
**以上图片版权属于此blog
答案 1 :(得分:1)
正如你所说:
Are the object names just a pointer to a location in memory
and both of these Points are pointing to one location?
是
用C语言,这将是这样的:
Point* p1 = (Point*)malloc(sizeof(Point));
Point* p2 = p1;
解决方案当然是在两个指针上有两个不同的对象:
Point* p1 = (Point*)malloc(sizeof(Point));
Point* p2 = (Point*)malloc(sizeof(Point));
或者像在Java中一样:
Point p1 = new Point(0, 0);
Point p2 = new Point(0, 0);
或者也许只是初始化第二个:
Point p2 = new Point(p1.getX(), p1.getY());
值得注意的是,对于Objects
,在Java中,==
运算符是引用相等,又名“这指向同一个对象”。如果要根据内容比较两个对象,则应覆盖.equals()
方法。大多数IDE可以根据给定类中的属性自动生成它。
答案 2 :(得分:0)
正如您已经猜到的那样,Java对象变量只是引用(指向内存的指针),因此编写
Foo a = new Foo();
Foo b = a;
只会创建一个 Foo
- 对象,现在由两个变量a
和b
引用。更改引用的对象b
也会更改引用的对象a
,因为它们引用同一个对象。
将两个引用与==
- 运算符进行比较将检查它们是否引用完全相同的对象。如果要根据值对两个对象进行比较,请使用equals()
- 方法:
Foo a = new Foo();
Foo b = new Foo();
if(a.equals(b))
System.out.println("It seems that Foo() generates Foos with the same values everytime");
使用.clone()
可以克隆一个对象,但是要小心它 - 它只会默认复制具有所有值的对象 - 不会调用构造函数,这会导致难以跟踪的错误调用构造函数很重要。我不建议在对象上使用.clone()
而不知道对他们的类进行安全。您始终可以实施自己的clone()
- 强烈推荐的方法。
答案 3 :(得分:0)
你是对的,虽然在Java中没有像指针那样的东西。两个变量(p1和p2)都是引用到内存中的同一个对象。
所以在你的情况下你可能想要这样的东西:
Point p1 = new Point(0, 0);
Point p2 = new Point(p1);
什么是非常重要: 比较两个对象时不要使用==运算符 - 而是使用.equals()
if (p1.equals(p2)) System.out.println("these are the same");
答案 4 :(得分:0)
Java(Object)的基类具有clone和equals方法,因此它是基本Java系统的一部分。但是,如果您阅读Object类的文档,它会对这些方法的作用有一些警告。我会使用以下内容并确保您对其进行测试以确保您获得所需的行为。
Point p1 = new Point(0, 0);
Point p2 = p1.clone();
if (p1.equals(p2)) System.out.println("these are the same");
答案 5 :(得分:0)
物体和记忆。
我希望很清楚图片中显示的是什么。最后@BBB和@CCC地址单元将是垃圾收集器的工作(因为它们现在都没有引用真实对象)。
我们可能会做一个测试,以显示真实物体的发生情况。
让我们创建简单的类。
class A {
private int value;
public A(int value) {
this.value = value;
}
public void increase() {
this.value++;
}
public int getValue() {
return value;
}
}
用于查看对象的内存链接如何更改的简单用法:
package test;
public class Starter {
public static void main(String[] args) {
A a = new A(1);
A b = new A(4);
A c = new A(7);
System.out.println("a.value= " + a.getValue());
System.out.println("b.value=" + b.getValue());
System.out.println("c.value=" + c.getValue());
System.out.println("\nMemory cells address: ");
System.out.println("a : " + a);
System.out.println("b : " + b);
System.out.println("c : " + c);
System.out.println("\nAfter b = a;");
b = a;
System.out.println("\nb : " + b);
System.out.println("\nAfter c = b;");
c = b;
System.out.println("c : " + c);
System.out.println("\nAfter a.increase(); All values of all objects will be same, because all of them are linked to one same memory address.");
a.increase();
System.out.println("a.value=" + a.getValue());
System.out.println("b.value=" + b.getValue());
System.out.println("c.value=" + c.getValue());
System.out.println("\nAfter c.increase(); All values of all objects will be same, because all of them are linked to one same memory address.");
a.increase();
System.out.println("a.value=" + a.getValue());
System.out.println("b.value=" + b.getValue());
System.out.println("c.value=" + c.getValue());
}
}
运行示例后,请注意对象引用(地址)
就我而言,我收到的内容如下:
a.value= 1
b.value=4
c.value=7
Memory cells address:
a : test.A@6d4b2819
b : test.A@6135b95d
c : test.A@e1cba87
After b = a;
b : test.A@6d4b2819
After c = b;
c : test.A@6d4b2819
After a.increase(); All values of all objects will be same, because all of them are linked to one same memory address.
a.value= 2
b.value=2
c.value=2
After c.increase(); All values of all objects will be same, because all of them are linked to one same memory address.
a.value=3
b.value=3
c.value=3