Man*_*uel 2 java arrays object
import java.util.Random;
public class B {
private class C {
int[] data = new int[5];
C (int[] input) {data = input;}
void print() {
for (int i=0; i<5; i++)
System.out.print(data[i] + " " );
System.out.println();
}
}
C[] c;
B () {
Random r = new Random();
c = new C[5];
int[] t = new int[5];
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++)
t[j] = r.nextInt(10) + 1;
c[i] = new C(t);
t = new int[5];
}
for (int k=0; k<5; k++)
c[k].print();
}
public static void main(String[] args) {
B b = new B();
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,C类是B的内部类.在B中,我有一个C类型的对象数组,恰当地称为"c".在C中,我有一个接受整数数组的构造函数.
我在这里做的是对于C数组中的每个元素,我正在生成一个包含5个整数的随机列表,并将其传递给相应C对象的构造函数.
此代码按预期工作; Cs数组中的每个对象都有一个不同的随机整数数组.但是如果我在第一个for循环的末尾删除行"t = new int [5]"(即,如果我没有"重置"t),那么我的Cs数组中的每个对象都会打印出来最后分配的5个数字.
换句话说,如果我改变这一点
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++)
t[j] = r.nextInt(10) + 1;
c[i] = new C(t);
t = new int[5];
}
Run Code Online (Sandbox Code Playgroud)
对此
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++)
t[j] = r.nextInt(10) + 1;
c[i] = new C(t);
}
Run Code Online (Sandbox Code Playgroud)
输出从此变化
9 6 5 3 7
2 7 7 3 9
4 5 8 3 9
9 8 3 5 8
4 8 5 5 4
Run Code Online (Sandbox Code Playgroud)
对此
7 1 5 8 9
7 1 5 8 9
7 1 5 8 9
7 1 5 8 9
7 1 5 8 9
Run Code Online (Sandbox Code Playgroud)
为什么会这样?不应该每个新的C对象都得到一组新的输入,因为在每次循环之后,t的内容都会改变,无论是否存在"t = new int [5]"行?
但是如果我在第一个for循环的末尾删除行"t = new int [5]"(即,如果我没有"重置"t),那么我的Cs数组中的每个对象都会打印出来最后分配的5个数字.
这是因为通过不创建新数组,您将使所有条目都c引用相同的数组.所以你自然会看到数组的相同内容.
我建议,因为t只对特定的循环迭代有用,你在循环中声明并创建它.请记住:变量的范围应尽可能窄.所以:
B () {
Random r = new Random();
c = new C[5];
// Don't declare or initialize it here: int[] t; = new int[5];
for (int i=0; i<5; i++) {
int t[] = new int[5]; // *** Keep it specific to the loop, and
// create a new one each iteration
for (int j=0; j<5; j++) {
t[j] = r.nextInt(10) + 1;
}
c[i] = new C(t);
}
for (int k=0; k<5; k++) {
c[k].print();
}
}
Run Code Online (Sandbox Code Playgroud)
为了说明创建新阵列和不创建新阵列时会发生什么,让我们为内存中的内容做一些ASCII艺术,但是使用3个元素而不是5个来保持图片更小:
每次使用该行创建一个新数组:
Random r = new Random();
c = new int[3];
int[] t = new int[3];
for (int i = 0; i < c.length; ++i) {
for (int j = 0; j < t.length; ++j0 {
t[j] = r.nextInt(10) + 1;
}
c[i] = t;
t = new int[3];
}
Run Code Online (Sandbox Code Playgroud)
在循环之前,我们在内存中有这个:
[t:Ref5462]???????????????????+
+????????????+ |
[c:Ref2534]??>| (array) | |
+????????????+ \ +?????????+
| 0: null | +?>| (array) |
| 1: null | +?????????+
| 2: null | | 0: 0 |
+????????????+ | 1: 0 |
| 2: 0 |
+?????????+
注意这些值t和c,我已经证明那里Ref5462和Ref2634分别.这些是对象参考.它们是值(就像int一个值),它们告诉Java运行时它们引用的数组在内存中的其他位置.即,该阵列是未在该变量,该位置阵列的是在变量.(我们从未看到实际值,我在这里使用的数字只是概念性的.)
然后我们运行j循环并填入以下值t:
[t:Ref5462]???????????????????+
+????????????+ |
[c:Ref2534]??>| (array) | |
+????????????+ \ +?????????+
| 0: null | +?>| (array) |
| 1: null | +?????????+
| 2: null | | 0: 9 |
+????????????+ | 1: 6 |
| 2: 5 |
+?????????+
然后我们存储的值的副本t中c[0]:
[t:Ref5462]???????????????????+
+????????????+ |
[c:Ref2534]??>| (array) | |
+????????????+ \ +?????????+
| 0: Ref5462 |???+?>| (array) |
| 1: null | +?????????+
| 2: null | | 0: 9 |
+????????????+ | 1: 6 |
| 2: 5 |
+?????????+
注意如何c[0]和t现在包含相同的值.它们都引用相同的数组.c[0]和之间没有联系t,它们只有相同的值.
然后我们创建一个新数组并将新引用存储在t:
[t:Ref8465]???????????????????????????????????+
+????????????+ |
[c:Ref2534]??>| (array) | |
+????????????+ +?????????+ |
| 0: Ref5462 |?????>| (array) | |
| 1: null | +?????????+ |
| 2: null | | 0: 9 | |
+????????????+ | 1: 6 | |
| 2: 5 | |
+?????????+ | +?????????+
+?>| (array) |
+?????????+
| 0: 0 |
| 1: 0 |
| 2: 0 |
+?????????+
请注意其中t有一个新引用,它指向新数组.c[0]仍然指向旧的.
现在我们再次循环并填写新的 t,然后将新t值存储在c[1]:
[t:Ref8465]???????????????????????????????????+
+????????????+ |
[c:Ref2534]??>| (array) | |
+????????????+ +?????????+ |
| 0: Ref5462 |?????>| (array) | |
| 1: Ref8465 |???+ +?????????+ |
| 2: null | | | 0: 9 | |
+????????????+ | | 1: 6 | |
| | 2: 5 | |
| +?????????+ \ +?????????+
+???????????????+?>| (array) |
+?????????+
| 0: 2 |
| 1: 7 |
| 2: 7 |
+?????????+
注意如何c[0]并c[1]引用不同的数组.
然后我们再次完成所有操作,创建另一个数组,并以此结束:
[t:Ref3526]??????????????????????????????????????????????????+
+????????????+ |
[c:Ref2534]??>| (array) | |
+????????????+ +?????????+ |
| 0: Ref5462 |?????>| (array) | |
| 1: Ref8465 |???+ +?????????+ |
| 2: Ref3526 |?+ | | 0: 9 | |
+????????????+ | | | 1: 6 | |
| | | 2: 5 | |
| | +?????????+ +?????????+ |
| +????????????????>| (array) | |
| +?????????+ |
| | 0: 2 | |
| | 1: 7 | |
| | 2: 7 | |
| +?????????+ \ +?????????+
+????????????????????????????????+?>| (array) |
+?????????+
| 0: 4 |
| 1: 5 |
| 2: 8 |
+?????????+
现在,让我们看一下如果你每次都不创建新的t:
Random r = new Random();
c = new int[3];
int[] t = new int[3];
for (int i = 0; i < c.length; ++i) {
for (int j = 0; j < t.length; ++j0 {
t[j] = r.nextInt(10) + 1;
}
c[i] = t;
// What if we leave this out? t = new int[3];
}
Run Code Online (Sandbox Code Playgroud)
起初,事情似乎是一样的.在这里,我们再次进行第一次循环:
[t:Ref5462]???????????????????+
+????????????+ |
[c:Ref2534]??>| (array) | |
+????????????+ \ +?????????+
| 0: Ref5462 |???+?>| (array) |
| 1: null | +?????????+
| 2: null | | 0: 9 |
+????????????+ | 1: 6 |
| 2: 5 |
+?????????+
但在这一点上,我们不会创建一个新的数组.所以在第二个循环之后,t引用的前一个数组中有新值,我们已将其位置的副本存储在c[1]:
[t:Ref5462]???????????????????+
+????????????+ |
[c:Ref2534]??>| (array) | |
+????????????+ \ +?????????+
| 0: Ref5462 |???+?>| (array) |
| 1: Ref5462 |??/ +?????????+
| 2: null | | 0: 2 |
+????????????+ | 1: 7 |
| 2: 7 |
+?????????+
现在t,c[0]和c[1]都指的是同一个阵列.在下一个循环之后,我们再次更新了该数组的内容并指向c[2]它:
[t:Ref5462]???????????????????+
+????????????+ |
[c:Ref2534]??>| (array) | |
+????????????+ \ +?????????+
| 0: Ref5462 |???+?>| (array) |
| 1: Ref5462 |??/ +?????????+
| 2: Ref5462 |?/ | 0: 7 |
+????????????+ | 1: 1 |
| 2: 5 |
+?????????+
所以很自然地,当你输出它时,你会看到重复相同的值.
| 归档时间: |
|
| 查看次数: |
1802 次 |
| 最近记录: |