【问题标题】:ArrayList and modifying objects included in itArrayList 和修改其中包含的对象
【发布时间】:2012-04-04 04:52:08
【问题描述】:

假设我们有一个 ArrayList myArray。我想通过调用它的函数来修改一个对象。如果我这样做,会不会改变原来的对象?

myArray.get(0).myModyfyingFunction();

为了进一步澄清 - 我担心 get() 是否实际上返回对我的原始对象的引用,或者它是否只返回我的原始对象的副本。

【问题讨论】:

  • 你为什么不试试看.. :) 就几行代码...
  • 查看这篇文章:javaranch.com/campfire/StoryPassBy.jsp(杯子概念中的全猫遥控器很棒)
  • 好点 @PrimosK :) 我想我想听听解释,并且我读过 Java 仅是按值传递。
  • @PrimožKralj - 如果您在按值传递和按引用传递的上下文中查看具有 C 背景的 java,这会令人困惑。从 C 的角度来看,Java 中的所有内容都是按值传递的。但是 Java 在 object references 上工作。查看here 以获得更好的想法。
  • 谢谢持戒者。还要感谢弗朗西斯科,我已经阅读了 JavaRanch 文章,现在它非常有意义。我也笑了,词的选择很好:)

标签: java arraylist pass-by-reference


【解决方案1】:

get() 将返回对对象的引用,而不是副本。您对返回的引用所做的任何修改都将在对象本身上进行

【讨论】:

  • 谢谢,我读过很多博客,上面说 Java 中的对象总是按值传递,这就是我感到困惑的原因。
  • 没错,所有的对象都是按值传递的。令人困惑的部分是,references 也是按值传递的——这意味着当您将一个对象添加到 ArrayList 时,您最终会得到两个指向同一个对象的引用,如果您修改一个引用,则“其他”也将被修改,因为两者都指向同一个对象
  • @PrimožKralj:“对象”不是 Java 中的值。永远不会传递或分配对象。您总是按值分配和传递引用
【解决方案2】:

如果您将任何对象存储在 ArrayList 中,则不会复制对象,并且对象中的任何更改都应反映在对象本身中。

例如我们有类 NewClass

  public class NewClass {

private String mystring="";

/**
 * @return the mystring
 */
public String getMystring() {
    return mystring;
}

/**
 * @param mystring the mystring to set
 */
public void setMystring(String mystring) {
    this.mystring = mystring;
}

}

这是任何其他类的主要方法中的代码

   List<NewClass> newclasses = new ArrayList<NewClass>();
    NewClass class1 = new NewClass();
    class1.setMystring("before1");
    NewClass class2 = new NewClass();
    class2.setMystring("before2");
    newclasses.add(class1);
newclasses.add(class2);
newclasses.get(0).setMystring("after1");
System.out.println(class1.getMystring());

这将在 1 之后输出。

【讨论】:

    【解决方案3】:

    这取决于您存储在 ArrayList 中的对象类型。 例如,如果它们是 java.lang.String s,则调用不会修改任何内容。 否则,是的,它会修改您存储在索引 0 处的对象。

    【讨论】:

    • 关于该方法的实现的好点,但我认为在这种情况下我们可以假设它实际上会修改它被调用的实例。 :)
    • 它不取决于它是什么类型的对象。这仅取决于方法的作用。字符串恰好没有任何改变它的方法
    • @newacct 那么,这不是说里面有“什么样的”对象吗?
    【解决方案4】:

    Java 从不返回对象的副本,只返回对象引用的副本。因此,该方法肯定会更改索引 0 处的对象。

    如果方法会创建一个对象,您可以获得对象的“副本”,例如如果可能,请使用return object.clone();,但实际上返回的是对仍在该方法中创建的副本的引用。因此,您可以获得更广泛意义上的对象的“副本”,但 ArrayList#get(...) 不会这样做 - 按照惯例,除非明确说明,否则 getter 都不应该这样做。

    【讨论】:

    • 谢谢,我的理解现在更好了;)
    【解决方案5】:

    它为您提供对象的引用,因此如果您的函数对其状态进行任何修改,您的对象将被修改。

    执行此操作时也会发生同样的情况:

    ArrayList myArray = new ArrayList();
    MyObject obj = new MyObject();
    myArray.add(obj);
    obj.myModifyingFunction();
    myArray.get(0).equals(obj); // returns true
    myArray.get(0) == obj; // returns true as well
    

    【讨论】:

    • myArray.get(0).equals(obj); 实际上甚至可能返回 true,如果 obj 不是同一个实例但只是逻辑上相等(取决于 equals() 的实现)。
    • 很好的观察,我修改了我的答案以澄清该对象已被修改并且它与添加的引用相同(并且它在逻辑上也是相等的)。
    • 感谢您的解释和提供的示例。
    【解决方案6】:

    更新列表中的对象:

    for (User user: Users) {
        user.setName( user.getName() + " New Name");
    }
    

    显示更新的对象

    for (User user: Users) {    
        System.out.println( user.getName());
    }
    

    【讨论】:

      【解决方案7】:

      这是一个例子。修改List中Test类的一个对象。

      public class ModifyArrayList {
      
          public static void main (String [] args) {
      
              List<Test> tests = new ArrayList<Test>();
      
              Test firstTest = new Test();
              firstTest.setId(100);
              firstTest.setName("John");
              tests.add(firstTest);
      
              Test secondTest = new Test();
              secondTest.setId(101);
              secondTest.setName("Tracy");
              tests.add(secondTest);
      
              Test thirdTest = new Test();
              thirdTest.setId(102);
              thirdTest.setName("Ryan");
              tests.add(thirdTest);
      
              ListIterator<Test> testIterator = tests.listIterator();
              while(testIterator.hasNext()) {
      
                  Test test = testIterator.next();
                  if (test.getName().equals("Ryan")) {
                      test.setId(300);
                  }
      
                  testIterator.remove();
                  testIterator.add(test);
              }
      
              for (Test test : tests) {
                  System.out.println("Test #" + test.getId() + " name=" + test.getName());
              }
      
          }
      }
      

      Test.java

      class Test {
      
          private int id;
          private String name;
      
          public int getId() {
              return id;
          }
      
          public void setId(int id) {
              this.id = id;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-10-11
        • 1970-01-01
        • 2016-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-18
        • 2020-01-21
        相关资源
        最近更新 更多