【问题标题】:changing of private variables改变私有变量
【发布时间】:2015-05-07 17:18:20
【问题描述】:

几个月以来,我一直在学习 Java 课程,并且正在尝试制作一个简单版本的口袋妖怪游戏。到目前为止,一切都很顺利,但现在我遇到了麻烦。

我有我的地图,其中障碍物存储在一个数组(私有)中的一个类中,并使用 get 方法在其他类中使用该数组。 这些其他类不知何故改变了第一类中的数组。

这怎么可能?

【问题讨论】:

  • 您应该共享代码,以便人们可以帮助您。
  • 阅读 this,它解释了 Java 如何处理对象的传递。您可能还想复习一下指针和引用。
  • 如果您使用 get() 方法提供对 Array 的访问权限,那么您将赋予其他人在拥有该数组后对其进行修改的能力。该数组是同一个对象,即它可能被定义在一个地方,但是 get() 提供了一个指向同一个数组的指针,这样任何“指向”该数组的人都可以看到对数组的更新,即使用对数组的引用。

标签: java private


【解决方案1】:

私有并不意味着它不能被变异。私有意味着该对象的引用不能直接使用父对象访问。如果你有一个 getter 并返回对象引用,那么任何具有该实例的对象都可以改变它。

【讨论】:

  • 谢谢你说清楚了。但是我怎样才能访问私有实例而不在 getter 中提供该引用?
  • 这里你要做的就是让你的数组不可变。这可以通过在 getter 方法中使用 Collections.unmodifiableList(Arrays.asList(your _array)) 将其作为不可修改的列表返回来完成。
【解决方案2】:

private 并不意味着你不能改变特定事物的价值。当您将变量设为私有时,它不能在类外直接访问。这意味着您不再能够访问如下类中的私有变量

class A{
    private int x = 10;
}

class B{
    public void m(){
         A a = new A();
         a.x = 20; // This is a compile error. Because x is not visible to outside of class A
    }
}

尽管您仍然可以通过公共方法访问该变量。也就是我们通常所说的封装。 例如

class A{
    private int x = 10;
    public int getX(){
        return x;
    }
    public void setX(int val){
        x = val;
    }
}

class B{
    public void m(){
         A a = new A();
         a.setX(20); 
    }
}

【讨论】:

    【解决方案3】:

    是的。通过使用反射,您可以访问您的私有字段而无需提供参考方法。
    例如:

    Field field = YourClass.class.getDeclaredField("fieldName");
    field.setAccessible(true); // Force to access the field
    // Set value
    field.set(yourClassInstance, "Something");
    // Get value
    Object value = field.get(yourClassInstance);
    

    【讨论】:

      【解决方案4】:

      没有看到您的代码,很难说出您的程序到底发生了什么。可能正在发生以下情况。

      也许你有一个类,它的方法返回一个可变的私有成员。当您这样做时,并且其他一些类调用此方法时,它将能够更改私有成员变量所引用的对象的内容。这是一个例子:

      import java.util.Arrays;
      
      class Example {
      
          // Private member variable
          private int[] data = { 1, 2, 3 };
      
          // Method that returns the private member variable
          public int[] getData() {
              return data;
          }
      
          public void showData() {
              System.out.println(Arrays.toString(data));
          }
      }
      
      public class Main {
          public static void main(String[] args) {
              Example example = new Example();
      
              // Prints: [1, 2, 3]
              example.showData();
      
              // Get the array
              int[] x = example.getData();
      
              // We can modify the array here!
              x[0] = 4;
      
              // Prints: [4, 2, 3]
              example.showData();
          }
      }
      

      这是因为对象是数组,datax 等变量是对同一个数组对象的引用 - 只有一个数组,datax 都引用到那个数组。如果修改数组,您将通过两个变量看到更改。

      如果你想避免这种情况,那么你不应该通过直接在类ExamplegetData() 方法中返回数组来公开数组。您应该复制该数组:

      public int[] getData() {
          // Return a copy of the array
          return Arrays.copyOf(data, data.length);
      }
      

      【讨论】:

      • 谢谢,问题就是这样。但是当我尝试使用副本解决方案时,它仍然会更改原始数组...
      • 那你没有正确制作副本,或者它以其他方式泄漏。
      • public static int[][] clone2D(int[][] array) { int[][] clone = new int[array.length][];诠释我; for (i = 0; i
      • 这样你只复制顶级数组。您还必须复制数组内的所有数组!否则,您只是在创建一个引用所有现有二级数组的新数组。
      • 这不是我用 for 循环做的吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-28
      • 1970-01-01
      • 2011-05-25
      • 2011-01-08
      • 1970-01-01
      • 1970-01-01
      • 2017-10-31
      相关资源
      最近更新 更多