【问题标题】:Adding an Object to Vector loses Reference using Java?向 Vector 添加对象会丢失使用 Java 的引用?
【发布时间】:2010-03-07 15:14:58
【问题描述】:

我有一个包含许多对象的向量。我的代码使用循环根据特定条件将对象添加到 Vector 中。我的问题是,当我将对象添加到 Vector 时,是原始对象引用添加到了 vector 还是 Vector 会创建对象的新实例并添加它?

例如在下面的代码中:

private Vector numbersToCalculate;
StringBuffer temp = new StringBuffer();

while(currentBuffer.length() > i) {
    //Some other code
    numbersToCalculate.add(temp);
    temp.setLength(0); //resets the temp StringBuffer
}

我正在做的是将“temp” StringBuffer 添加到 numbersToCalculate 向量中。我应该在循环中创建一个新的 StringBuffer 并添加它还是该代码可以工作?感谢您的帮助!

埃里克

【问题讨论】:

    标签: java vector stringbuffer


    【解决方案1】:

    您每次都需要创建一个新的 StringBuffer。 Vector 中的每个 item item 只是指向同一个 StringBuffer 对象的指针,因此每次通过循环时,您都会重置 stringbuffer 的单个实例并添加对 Vector 的相同引用。

    只需将temp.setLength(0); 替换为temp = new StringBuffer();

    【讨论】:

      【解决方案2】:

      如果必须将独立对象添加到 Vector,请每次创建一个新对象。

      您正在添加对向量的引用。如果一个对象的状态发生变化,那么所有对它的引用都会看到变化。

      【讨论】:

        【解决方案3】:

        它每次都使用同一个对象。您应该在循环末尾添加 temp = new StringBuffer();。 (循环的结果将是指向同一个空 StringBuffer 的指针向量。)

        【讨论】:

          【解决方案4】:

          Vector 将存储您给它的引用,它不会创建自己的对象副本。因此,如果您希望 Vector 将缓冲区与您继续使用的缓冲区分开,正如您所说,您需要通过创建新缓冲区而不是将旧缓冲区的长度设置为零来单独创建这些缓冲区。

          题外话:Vector 已经过时了。使用ArrayList(或实现List 的其他类之一,如果您不需要支持它的数组)可能会更好。

          【讨论】:

          • 如果你用更新的东西替换Vector,那肯定是ArrayList?为什么要在这里使用地图?
          • @DaveJohnston:谢谢,脑力衰竭,自从我处理旧的 util 类以来已经那么了。我在想Hashtable。固定。
          • ArrayList 不同步,Vector 是。如果多个线程正在访问数组,我想使用 ArrayList 的 Vector,对吗? Vector优于ArrayList有什么缺点?
          • @thechiman:不,我可能会单独且明确地处理同步(请参阅 ArrayList 概述 [1] 上的同步说明),通过 syncrhonizedList 使用同步版本 [2],或者考虑一些事情来自java.util.concurrent,例如CopyOnWriteArrayList[3]。链接:[1]java.sun.com/javase/6/docs/api/java/util/ArrayList.html[2]java.sun.com/javase/6/docs/api/java/util/…[3]java.sun.com/javase/6/docs/api/java/util/concurrent/…
          • @thechiman(继续):Vector 和您从`synchronizedList` 返回的列表是每个方法调用都是单独同步的。因此,如果您执行一系列方法调用,则必须为该系列中的每个调用单独获取锁,这可能不太理想。进行自己的同步可以让您直接控制同步的粒度。
          【解决方案5】:

          将元素插入集合不会也不能复制对象,因为 Java 没有针对用户定义类型的复制构造函数或运算符重载的正式概念。也就是说,通用集合无法知道如何复制包含的对象。

          Java 的赋值运算符总是复制用户定义类型的指针,而不是内容。

          【讨论】:

            【解决方案6】:

            正如这里的大多数答案所说,Vector 存储对Object 类型对象的引用。如果您每次更改底层的Object,您最终会得到一个Vector,其中包含对一个对象的大量引用,该对象现在包含您给它的最后一个值。

            根据您的变量名称,我猜您实际上想在 Vector 中存储数字。

            在理想情况下,您只需将 int 类型的对象添加到 Vector 中。不幸的是,在 Java 中,int 是“原始类型”,Vector 只能存储 Object 类型的对象。这意味着您只能将 Integer 对象放入 Vector 而不是 int 对象。

            所以你的代码看起来像:

            // Put a number at index 0
            Integer inputNumber = new Integer(7);
            numbersToCalculate.add(0, inputNumber);
            
            // Some time later read out the value at index 0
            Object objFromVector = numbersToCalculate.elementAt(0);
            
            // Cast the Object to an Integer
            Integer numberToProcess = (Integer)objFromVector;
            

            如果Vector 包含不是Integer 对象的内容,此代码将抛出IllegalCastException。如果您对此感到担心,可以将其包含在 try catch 声明中。

            在您的示例中,您可能只想遍历 Vector 中的所有数字。您可能还希望对 Vector 可以包含哪些对象(称为“泛型”,类似于 C 模板)更加规范。下面是它的样子:

            Vector<Integer> myVector = new Vector<Integer>();
            
            // Add stuff to the Vector
            
            for (Integer number : myVector)
            {
                // Do stuff with the number
            }
            

            foreach 和泛型结构仅在 Java SDK 1.5 中添加,因此如果您想在早期的 Java SDK 上运行,则不能使用它们。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-09-15
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多