【问题标题】:Java objects confusionJava 对象混淆
【发布时间】:2012-07-30 08:42:41
【问题描述】:

我目前正在创建一个Android应用,并认为我遇到了saving data internally等问题。结果发现问题与此无关,而是与我对Java的理解有关。

问题是当我这样做时

myObject1 = myObject2;

并在myObject3 中使用myObject1,这可能是一个列表,或者其他任何东西(在我的情况下是一个哈希表),然后更改myObject2,myObject3 也会相应地更改。这叫什么,我在哪里可以了解更多信息?如何将myObject2 分配给myObject1 以使myObject1 完全“独立”?

【问题讨论】:

    标签: java android object pointers


    【解决方案1】:

    当您将一个对象 o1 分配给另一个对象 o2 时,您使 o2 指向 o1。因此,每当您更改对象 o1 时,对象 o2 都会相应更改。

    列表中的对象也是如此。这是因为在 Java 中,当您将一个对象分配给另一个对象时,您不会复制内容,而是“共享”它。

    创建独立于所有对象的另一个对象的唯一方法是使用 new,然后复制每个属性。

    【讨论】:

      【解决方案2】:

      这取决于myObject 是什么。如果您想要准确的副本,您正在寻找的词是 clone。但并非所有对象都支持克隆,因此您可能必须构建自己的克隆方法(正如@Hunter 指出的那样)需要通过 new 关键字分配新内存。

      【讨论】:

        【解决方案3】:

        变量包含对对象的引用。在其他语言中,引用通常称为指针。这样做myObject1 = myObject2; 会使myObject1 变量引用与myObject2 变量相同的对象。

        如果你想复制一个对象,最好的方法是自己实现它,例如使用复制构造函数:

        public MyClass(MyClass other) {
            this.foo = other.foo;
            this.bar = other.bar;
            ...
        }
        

        于是就这样做了

        myObject1 = new MyClass(myObject2);
        

        【讨论】:

          【解决方案4】:

          所以在 Java 或任何 OOP 语言中

          如果你考虑这个陈述

          Object obj = new Object()
          

          obj 被称为句柄,它实际上指向存储实际对象的位置。

          所以当您执行obj1 = obj 时,您将获得 2 个实际上指向同一位置的句柄

          因此,如果您执行obj1.setSomething(),它也会反映在obj.getSomething() 调用中。

          【讨论】:

            【解决方案5】:

            Java 中作为对象的变量称为引用,引用到内存中的同一位置。如果您希望两个相同类型的对象不引用内存中的同一位置,则需要使用new 关键字在您的计算机上为它们分配内存。

            myObject1 和 myObject2 两个变量下面是对 OBJECT1 对象的引用,但它们不存在于同一内存位置:

            OBJECT1 myObject1 = new OBJECT1();
            OBJECT1 myObject2 = new OBJECT1();
            

            如果将一个对象分配给另一个对象很重要,您可以查看clone() 方法或使用复制构造函数:

            public OBJECT1(OBJECT1 toCopy)
            {
                this.field1 = toCopy.field1; 
                this.field2 = toCopy.field2; 
                this.field3 = toCopy.field3; 
                this.field4 = toCopy.field4;     
            }
            

            【讨论】:

            • 还有一个问题:如果我的 OBJECT1 是一个二维数组,那会怎样?
            • @sk1ll3r 你想进行类似的复制吗?然后,您必须遍历所有行和列并将它们复制到新数组中的相应值。这是一个很好的帖子,有一个例子:stackoverflow.com/questions/5617016/…
            • 好的,这就是我使用的。我只是问如果没有循环就没有办法做到这一点,因为它只会让代码变得混乱。
            • 如果你想要一个深拷贝就不行,这意味着一个数组中的元素不会通过引用链接到新数组。如果您不介意浅拷贝,您可以使用 System.arraycopy() : docs.oracle.com/javase/7/docs/api/java/lang/…
            【解决方案6】:

            这些变量是对象的引用;将每个变量视为字符串的结尾。另一端与物体相连。如果您分配一个变量,您就是将一个新字符串绑定到一个对象上。

            要创建副本,您(不出所料)需要创建副本。有时,这很容易:可能有一个 复制构造函数 可以让你这样做:

            ArrayList<String> copy = new ArrayList<String>(oldArrayList);
            

            其他时候,你可能是一个复制的方法;例如,一些类实现了clone() 方法:

            Foo copy = (Foo) otherFoo.clone();
            

            您只需研究一个类的 API 即可找到复制对象的方法。

            【讨论】:

            • 需要注意的是,虽然ArrayList 的复制构造函数可能会创建oldArrayList 的新副本(即列表),但它并不一定会给你一个新的元素副本oldArrayList。执行copy.get(0).someOperation() 可能会写回oldArrayList 元素0,具体取决于复制构造函数的定义方式。
            • 确实,它不复制元素,只复制列表本身,因此您可以在一个副本中添加和删除元素,而不会影响另一个副本中元素的数量或顺序。
            猜你喜欢
            • 1970-01-01
            • 2010-11-30
            • 2022-11-22
            • 2017-01-11
            • 1970-01-01
            • 1970-01-01
            • 2012-05-21
            • 2023-03-03
            • 2013-03-30
            相关资源
            最近更新 更多