欺骗 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 实例的引用(例如 StringInteger).

您的作业:

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的值。