我正在创建一个具有一个数组作为其私有成员的类,并为此实现了getter,setter方法。我想使用main函数中的数组为该数组设置一个值。当我在main函数中操作数组时,它不应影响该类中存在的数组。
我尝试了这段代码,但是在这里数组被操纵了
class ClassB {
private int[] a;
ClassB() { }
ClassB(int[] a) {
this.a=a;
}
int[] geta() {
return this.a;
}
void seta(int a[]) {
this.a = a;
}
}
public class ClassA{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter size : ");
int n = sc.nextInt();
int[] d = new int[n];
System.out.println("Enter array elements : ");
for (int i=0 ; i<n ; i++) {
d[i] = sc.nextInt();
}
final ClassB cb2 = new ClassB(d);
d[3] = 15;
System.out.println("After changing array d : \n Values of array d :");
for (int i=0 ; i<n ; i++) {
System.out.println(d[i]);
}
System.out.println("Values of array a of cb2 :");
int[] b = cb2.geta();
for (int i=0 ; i<n ; i++) {
System.out.println(b[i]);
}
}
}
我希望:
Enter size :
5
Enter array elements :
1
2
3
4
5
After changing array d :
Values of array d :
1
2
3
15
5
Values of array a of cb2 :
1
2
3
4
5
但是实际输出是:
Enter size :
5
Enter array elements :
1
2
3
4
5
After changing array d :
Values of array d :
1
2
3
15
5
Values of array a of cb2 :
1
2
3
15
5
答案 0 :(得分:3)
每次设置数组或需要返回其值时,都可以在ClassB
中创建防御性副本。像这样:
class ClassB {
// ... code omitted for brevity
ClassB(int[] a) {
seta(a);
}
int[] geta() {
int[] copy = new int[a.length];
System.arraycopy(a, 0, copy, 0, a.length);
return copy;
}
void seta(int a[]) {
this.a = new int[a.length];
System.arraycopy(a, 0, this.a, 0, a.length);
}
}
旁注:
ClassB
不可变,那么您就不需要为其值设置二传手。System.arraycopy
用于创建阵列的副本。随时可以在这里使用更适合您需要的内容(您可能要考虑使用Lino在下面的评论中建议的a.clone()
...这是一个不错的话题:Why clone() is the best way for copying arrays?)。其他阅读材料:
答案 1 :(得分:1)
执行final ClassB cb2 = new ClassB(d);
时,实际上是将数组 b 的 reference 传递给ClassB
。由于两个引用相同,因此ClassB
中的数组正在更改。
必须阅读-Is Java “pass-by-reference” or “pass-by-value”?
如果要对d
进行的更改不影响ClassB
内的数组,则必须制作该数组的副本。将您的构造函数更改为以下内容:
ClassB(int[] a) {
this.a = a.clone();
}
注意:
此外,使ClassB
对象成为最终对象(final ClassB cb2
)会使其对象cb2
不可变。不是里面的物体。
因此,当您执行以下操作时,您不能更改cb2
,但可以肯定地更改cb2.a
:
final ClassB cb2 = new ClassB(d);