欺骗 Java 中的私有关键字
Trick the private keyword in Java
我知道关键字 private 的想法是启用封装。然而,当我意识到我可以在用 getter 检索数组后修改它时,我感到困惑,这让我感到惊讶。虽然我认为 java 将所有变量都视为对象,但同样不适用于普通整数。
例子:
public class PrivContainer {
private int[] myIntArray;
private int myInt;
PrivContainer(){
myIntArray=new int[1];
myIntArray[0]=3;
myInt=22;
}
public int[] getIntArray(){
return myIntArray;
}
public int getInt(){
return myInt;
}
public void printInt(){
System.out.println(myIntArray[0]);
System.out.println(myInt);
}
}
public class Main {
public static void main(String[] args){
PrivContainer pc=new PrivContainer();
int[] r=pc.getIntArray();
int q=pc.getInt();
r[0]=5;
q=33;
pc.printInt();
}
}
printInt()
的输出是5,22
这意味着 main 方法可以更改私有 array
的条目,但不能更改私有 int
.
的条目
谁能给我解释一下这个现象?
数组是一个可变对象。因此,如果您有对该数组的引用,则可以修改其内容。您不能对 class 的原始成员(例如 int
)和对不可变 class 实例的引用(例如 String
和 Integer
).
您的作业:
q=33;
类似于:
r = new int [5];
这两个赋值都会导致变量包含新值,但它们不会影响 PrivContainer
实例的状态,这些变量的原始值是从中赋值的。
这里似乎没有什么奇怪的。大致情况如下。
public class Main {
public static void main(String[] args){
PrivContainer pc=new PrivContainer(); <-- create new `PrivContiner` object which also initialised the private variables
int[] r=pc.getIntArray(); <-- you get the "object" integer array here and assign r to refer to that object
int q=pc.getInt(); <-- you get the "primitive" integer here and assign q to refer the myInt variable here.
r[0]=5; <-- you assign the first value of the array 5. Note that the object reference is still the same here
q=33; <-- you assign the variable q to 33. Note that, this mean, the variable q refer to another primitive here (which is 33)
pc.printInt(); <-- print the content of the object here.
}
}
当您调用 printInt
函数时。输出将是 5 和 22,因为新整数 (33) 已分配给 q
,并且其范围仅在 main
函数内。
当您 return 来自 getter 的数组时,您 return 该对象的引用。由于您有参考,您可以更改其元素。如果你想避免这种行为,你将不得不 return 克隆你的数组,在这种情况下你将无法更改数组的元素
public class Main {
public static void main(String... args) {
Arr arr = new Arr();
int[] y = arr.getX();
y[1] = 5;
System.out.println(arr.getX()[1]);
}
}
class Arr {
private int[] x = {1, 2, 3};
public int[] getX() {
return x.clone();
}
}
试试这段代码并删除克隆方法,就像这样
class Arr {
private int[] x = {1, 2, 3};
public int[] getX() {
return x;
}
}
现在执行main
方法,你会发现改变y
的值也会改变数组x
的值。
我知道关键字 private 的想法是启用封装。然而,当我意识到我可以在用 getter 检索数组后修改它时,我感到困惑,这让我感到惊讶。虽然我认为 java 将所有变量都视为对象,但同样不适用于普通整数。
例子:
public class PrivContainer {
private int[] myIntArray;
private int myInt;
PrivContainer(){
myIntArray=new int[1];
myIntArray[0]=3;
myInt=22;
}
public int[] getIntArray(){
return myIntArray;
}
public int getInt(){
return myInt;
}
public void printInt(){
System.out.println(myIntArray[0]);
System.out.println(myInt);
}
}
public class Main {
public static void main(String[] args){
PrivContainer pc=new PrivContainer();
int[] r=pc.getIntArray();
int q=pc.getInt();
r[0]=5;
q=33;
pc.printInt();
}
}
printInt()
的输出是5,22
这意味着 main 方法可以更改私有 array
的条目,但不能更改私有 int
.
谁能给我解释一下这个现象?
数组是一个可变对象。因此,如果您有对该数组的引用,则可以修改其内容。您不能对 class 的原始成员(例如 int
)和对不可变 class 实例的引用(例如 String
和 Integer
).
您的作业:
q=33;
类似于:
r = new int [5];
这两个赋值都会导致变量包含新值,但它们不会影响 PrivContainer
实例的状态,这些变量的原始值是从中赋值的。
这里似乎没有什么奇怪的。大致情况如下。
public class Main {
public static void main(String[] args){
PrivContainer pc=new PrivContainer(); <-- create new `PrivContiner` object which also initialised the private variables
int[] r=pc.getIntArray(); <-- you get the "object" integer array here and assign r to refer to that object
int q=pc.getInt(); <-- you get the "primitive" integer here and assign q to refer the myInt variable here.
r[0]=5; <-- you assign the first value of the array 5. Note that the object reference is still the same here
q=33; <-- you assign the variable q to 33. Note that, this mean, the variable q refer to another primitive here (which is 33)
pc.printInt(); <-- print the content of the object here.
}
}
当您调用 printInt
函数时。输出将是 5 和 22,因为新整数 (33) 已分配给 q
,并且其范围仅在 main
函数内。
当您 return 来自 getter 的数组时,您 return 该对象的引用。由于您有参考,您可以更改其元素。如果你想避免这种行为,你将不得不 return 克隆你的数组,在这种情况下你将无法更改数组的元素
public class Main {
public static void main(String... args) {
Arr arr = new Arr();
int[] y = arr.getX();
y[1] = 5;
System.out.println(arr.getX()[1]);
}
}
class Arr {
private int[] x = {1, 2, 3};
public int[] getX() {
return x.clone();
}
}
试试这段代码并删除克隆方法,就像这样
class Arr {
private int[] x = {1, 2, 3};
public int[] getX() {
return x;
}
}
现在执行main
方法,你会发现改变y
的值也会改变数组x
的值。