两个新创建的对象似乎引用相同的地址

我用Java编程只用了几个月,所以我不熟悉Java(有些技巧和我应该知道的基本知识)。

我遇到了一个可能很明显但我看不到的问题。

public class SomeClass { private final int[] numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; private LabelText AText = new LabelText('A', numbers); private LabelText BText = new LabelText('B', numbers); public void foo() { AText.numbers[6] = -1; BText.numbers[3] = -1; if (BText.numbers[6] == -1) System.out.println("Wtf?"); } } 

这是我的代码摘录。

这怎么可能是真的? 这是两个独立的对象。 我不明白。

foo方法直接在我的main方法中调用(用于测试目的)。

如果你需要LabelText的构造函数,这里是:

 public class LabelText { private final char letter; public int[] numbers; public LabelText(char letter, int[] numbers) { this.letter = letter; this.numbers = numbers; } } 

因为您在不进行复制的情况下传递对numbers引用 ,所以两个对象最终都指向同一个 int[] 实例 。 虽然有两个不同的外部对象,但它们指向的内部对象是同一个对象 ,因此您可以通过取消引用AText.numbersBText.numbers任何一个来更改该内部对象,并且更改将在两个中都可见。访问其numbers字段时的外部对象。

您可以检查AText == BText将返回false ,但AText.numbers == BText.numbers将返回true 。 并且this.numbers == AText.numbers也将返回true

就像尝试这个相同的代码,但使用此构造函数:

 public LabelText(char letter, int[] numbers) { this.letter = letter; this.numbers = numbers.clone(); // so it will always be unique array here } 

Java中的Object Refreneces:

在Java编程语言中,有两种数据类型:原始和引用。

  • 基元:char,byte,short,int,long,float和double
  • 参考:Java和数组中的所有对象。

示例Java对象:

  • 在Java编程语言中,有类,如StringExceptionIntegerFile 。 使用这些类创建对象。 此外,可以创建自定义类和对象 – 例如PersonLabelText

Java对象的创建如下。 如果Person是一个类:

 public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public void setName(String s) { name = s; } public String getName() { return name; } public void setAge(int i) { age = i; } public int getAge() { return age; } } 

考虑一下代码:

 Person personA = new Person("A", 32); 

在上面的语句中, Person是一个类, personA是一个变量, new Person(..)创建一个Person类型的对象。 =将新创建的Person对象分配给变量personApersonA是引用类型的变量,它指向或引用新创建的Person对象。

Person类具有属性(或属性) nameage 。 这些代表对象的状态 。 通常,状态区分对象。

该引用类型的行为如何? 查看此示例代码:

 public class TestingReferences { public void foo() { Person a = new Person("A", 32); // 1 Person b = new Person("B", 28); // 2 Person c = a; // 3 a.setName("X"); // 4 System.out.println("Are the names of a and c equal? " + a.getName().equals(c.getName())); // 5 } } public static void main(String [] args) { TestingReferences app = new TestingReferences(); app.foo(); } } 

在上面的示例代码中,注意在方法foo()打印的输出 – 人员ac都具有相同的名称X. 这是怎么发生的?

1: Person a = new Person("A", 32); 创建一个新的人物对象并将其分配给变量a
2: Person b = new Person("B", 28); 创建一个新的人物对象并将其分配给变量b
3: Person c = a; 创建人员变量c – 并且 – 为其分配参考变量a 。 在此阶段,引用变量ac都指向或引用同一个人对象(见下图)。
4: a.setName("X"); 人物对象的name从“A”变为“X”。
5: System.out.println("Are the names of a and c equal? " + a.getName().equals(c.getName())); 这打印true

由于引用变量ac都指向同一个对象,因此两个引用都可以看到对象状态的任何更改。

如果语句被添加到fooc.setAge(44);ac人的age都设定为44岁。

在此处输入图像描述

上面的示例演示了对象引用在Java编程语言中的行为方式。 同样适用于这篇文章中的问题。


从post的问题:

请注意,数组,两个基元数组(如int[] )和对象数组( Person[] )始终是对象。

1: private final int[] numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
2: private LabelText AText = new LabelText('A', numbers);
3: private LabelText BText = new LabelText('B', numbers);

上述三个语句中有三个对象和引用变量。 注意, numbers对象引用被分配给ATextBText的状态。 numbers数组的所有这三个引用都指向在第1行上创建的相同数组对象。 现在,在方法foo()

 AText.numbers[6] = -1; BText.numbers[3] = -1; (BText.numbers[6] == -1) ... returns true -and- (AText.numbers[3] == -1) ... also, returns true. 

将此语句添加到方法fooSystem.out.println(java.util.Arrays.toString(numbers)); 这打印: [0, 1, 2, -1, 4, 5, -1, 7, 8, 9] 。 注意位置36中的数组值。