【问题标题】:Private variable getting exposed/modified私有变量被暴露/修改
【发布时间】:2018-10-15 19:43:24
【问题描述】:

我很困惑为什么我的私有变量会被其他类公开和修改,这让我很沮丧,因为我无法弄清楚我的概念/理解哪里出了问题。请帮忙。

Test.java

public class Test {
    private String[] privateStringArr = new String[10];

    Test() { }

    public String[] getStringArr() {
        String[] cover = privateStringArr;
        return cover;
    }
}

Main.java

public class Main {
    static Test testClass = new Test();
    static String[] shouldBePrivate = testClass.getStringArr();

    public static void main(String[] args) {
        System.out.println(testClass.getStringArr()[0]);
        shouldBePrivate[0] = "hello";
        System.out.println(shouldBePrivate[0]);
        System.out.println(testClass.getStringArr()[0]);
    }
}

输出:

null
hello
hello

为什么修改shouldBePrivate 也修改testClass 中的privateStringArr

提前致谢

【问题讨论】:

  • 这根本不是私人的!
  • 私有只是意味着你不能直接使用变量名来访问变量,比如testClass.privateStringArr

标签: java private public


【解决方案1】:

因为你在这里返回了指向同一个对象的链接

public String[] getStringArr() {
        String[] cover = privateStringArr; // <- no new object is created
        return cover;
    }

您可以改为返回副本

public String[] getStringArr() {
        return privateStringArr.clone();
    }

【讨论】:

    【解决方案2】:

    public String[] getStringArr() 中,您正在传递对StringArr 的非私有引用:

    public String[] getStringArr() {
        String[] cover = privateStringArr;
        return cover;
    }
    

    因此,在您的主体中,您可以对其进行修改。您需要返回privateStringArr 的真实副本。您可以使用clone()System.arrayscopy()

    【讨论】:

      【解决方案3】:

      经过以下步骤:

      static String[] shouldBePrivate = testClass.getStringArr();
      

      shouldBePrivate 的所有修改都会影响privateStringArr,因为它们是对同一个数组对象的引用。两个变量引用同一个数组。如果修改数组,两个变量都会受到影响。

      为了避免这种情况,return Arrays.copyOf(privateStringArr , privateStringArr .length); 应该返回到getStringArr()

      【讨论】:

        【解决方案4】:

        在 Java 中,几乎所有内容(除了原始值,如 intchar)都是 referencepointer - 存储在变量中的不是值本身,而是实际数据所在的内存地址。

        cover = privateStringArr
        shouldBePrivate = testClass.getStringArr()
        

        这两个赋值不会复制 Java 中的实际数据——它们只是复制内存中数据所在的地址。

        private String[] privateStringArr = new String[10]; // create an array of 10 Strings, and store the address in privateStringArr
        String[] cover = privateStringArr;                  // copy address to cover
        return cover;                                       // return the address stored in cover
        String[] shouldBePrivate = testClass.getStringArr();// copy returned address to shouldBePrivate
        shouldBePrivate[0] = "hello";                       // find the data at address read from shouldBePrivate and modify it's first element
        testClass.getStringArr()[0]                         // find the data at address returned from getStringArr() and read the first element
        

        【讨论】:

        • 我明白了,所以如果我使用.clone() 方法,它会为我的变量创建一个新的内存地址?
        • clone() 将在内存中分配新位置,从原始位置复制数据并返回这个新地址。但是,请注意两件事:a)您需要了解 shallow copy vs deep copy 的区别,以及 b)the clone() method is broken 应该尽量避免。 clone() 本身进行浅拷贝,在您的简单情况下应该足够了,但如果您的数组项是可变类型而不是 String,则可能还不够。
        猜你喜欢
        • 2018-06-19
        • 1970-01-01
        • 1970-01-01
        • 2016-09-15
        • 1970-01-01
        • 1970-01-01
        • 2021-08-01
        • 2018-09-14
        • 2019-07-01
        相关资源
        最近更新 更多