ArrayList引用行为

时间:2012-02-12 02:36:32

标签: java reference arraylist

我对ArrayList行为感到困惑。写了很长的帖子,然后意识到没有人会分析大量的代码,所以只是问题的核心。数字是为了方便,但在我的应用程序中,这些0和24是动态值。

ArrayList<VoipBlock> sortedBlocks = new ArrayList<VoipBlock>();

VoipBlock vb3 =new VoipBlock();

vb3=sortedBlocks.get(0);

vb3.setPacketNumber(24); 

基本上我的最终目标是:修改并添加回arrayList作为新值。然而,当我这样做时,ArrayList中位置0的那个人 - &gt; unsortedBlocks.get(0); 复制对 vb3 所做的所有更改,这当然不是我想要的。我希望vb3在ArrayList中获取与VoipBlock相同的值,但我希望它能够分离。

这是通过引用传递的另一种情况。我讨厌技术解释 - Java按值传递所有内容,但在某些情况下它会通过值传递引用 - 这与非油性油相同。请帮忙。

这让我想起了我开始学习JavaScript - 我讨厌这种语言 - 直到我在lynda.com上观看了适当的材料 - JavaScript Good Practices? - 图表杀了我。正是这种懒惰的描述使我们 - 青年远离了辉煌的技术,而不是技术本身。

请不要让它困扰我的压力,不要以任何方式冒犯我,这只是一般的抱怨,也许有人会看着它,让生活更美好: - )

谢谢你的时间, 拼命等待帮助: - )

4 个答案:

答案 0 :(得分:1)

以下内容总是将b的引用复制到:

AnyClass a = ...;
AnyClass b = ...;
a = b;

你想要的可能是克隆对象:

a = b.clone();

答案 1 :(得分:1)

如果我理解正确,你对参考和价值观如何运作有点不确定。我认为经验法则是复制原始类型,如int, char, booleanString,但对象只是传递了它们的参考。

vb3=sortedBlocks.get(0);完全替换了ArrayList中第一个用的vb3。是的,它不会是一个副本,它将是对内存中同一个对象的引用。所以无论你做什么都会影响他们。您需要手动复制所需的所有信息,或使用clone()copy()功能。

例如,在您的代码中,行VoipBlock vb3 =new VoipBlock();有点多余,因为您将立即覆盖新实例。

答案 2 :(得分:1)

要实现您的目标,您可以使用克隆方法。你必须在VoipBlock类中重写这个方法

让我们说VoipBlock如下

public class VoipBlock {

     private int packetNumber;
     private String type;

     public int getPacketNumber() {
      return packetNumber;
     }

     public String getType() {
      return type;
     }

     public void setPacketNumber(int value) {
       packetNumber = value;
     } 

     public void setType(String value) {
       type = value
     }

     public VoipBlock clone() {
        VoipBlock clone = VoipBlock();
        clone.setType(this.getType());
        clone.setPacketNumber(this.getPacketNumber());
        return clone;
     }

}

因此,您可以使用相同的代码,如下所示

ArrayList<VoipBlock> sortedBlocks = new ArrayList<VoipBlock>();

VoipBlock vb3 =new VoipBlock();

sortedBlocks.add(vb3);

vb3=sortedBlocks.get(0).clone();

vb3.setPacketNumber(24);

请注意,在上面的代码段中调用clone方法后,vb3会分配一个新的VoipBlock实例。已插入的VoipBlock保持不变。

如果你想要有一些VoipBlock实例的样本实例,你后来想用它来创建类似它们的类似实例。检查代码的不变性/可变性方面。查看Joshua Blouch的“Effective Java”

答案 3 :(得分:0)

您真正需要的是使用复制构造函数或声明VoipBlock为Clonable,以便您可以使用clone()方法。

您通过引用传递的内容实际上并未通过引用传递。 Java对象确实是指针。因此,您传递指针的值。所以当你这样做时:

vb3=sortedBlocks.get(0);

你真的指定vb3指向内存中与sortedBlocks.get(0)相同的位置。因此,当您通过其setter操作vb3属性时,结果将在两者中看到。

如果您需要两个单独的指针,则需要使用 new 关键字或使用clone()方法来完成此操作。

证明这一点的一个例子是:

public class Person {
  private String name;

  public Person(String name) {
    this.name = name;
  }

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
     this.name = name;
  }
}

public class Main {

  public void doSomething(Person p) {
    p = new Person("Bob");
    System.out.println(p.getName());
  }

  public static void main(String[] args) {
    Person p = new Person("Billy");
    System.out.println(p.getName());
    doSomething(p);
    System.out.println(p.getName());
  }
}

由于Java是按值传递的,因此输出将是:Billy,Bob,Billy。如果Java通过引用传递,那么将是Billy,Bob,Bob。如果我没有在doSomething()方法中执行新Person,而是使用setName()方法,我最终会遇到Billy,Bob,Bob,但这是因为我现在正在修改相同的指针而不是我通过引用传递过去的例子证明情况并非如此。