我是在修改该对象的对象还是副本?

时间:2012-02-21 21:53:11

标签: java arrays casting

我正在查看一些代码,并且我想确保我理解是否对对象进行了某些更改,实际上是对这些对象或这些对象的副本进行了更改。

以下是一个示例:

for(int i = 0; i < myList.size(); i++)
{
    DataObject myItem = (DataObject)myList.get(i);
    myItem.setString("someKey", "someValue"); 
}

myList是一个DataObjects列表,所以我不确定在调用列表中的get()方法后将项目转换为DataObject的目的是什么。但是我想知道在编译它时如何处理这个问题 - 演员是否会创建一个新对象,然后将在该新对象上调用setString()方法而不影响列表中的对象?或者是myItem引用列表中的实际项目吗?

感谢。

8 个答案:

答案 0 :(得分:2)

在投射后,它仍然是对列表中项目的引用。未创建副本。

List返回Object类的类型,以便它可以用于任何类型的Object(因为所有类都扩展为Object)。为了调用setString,您需要将引用类型转换为更具体的引用类型,以便编译器知道您调用它的对象类型。

使用泛型,例如List与您的列表一起指定类型将意味着您不必进行强制转换,但如果您无法控制列表创建或不知道或想要限制哪些类型的对象可能不适合在其中。

答案 1 :(得分:1)

演员阵容不会创建新对象,它只会告诉编译器'嘿,我知道我在做什么,这是DataObject'。

在不知道实际List实现的类型的情况下,我们不能说你得到的是同一个对象。如果您正在使用Java Collections集合之一(ArrayList,LinkedList等),那么它将是相同的对象实例。但我可以想象一个实现(当然由我自己制作!),它可以返回副本而不是底层实例。

public class MyList<T> implements List<T> {
    private List<T> backingList = new ArrayList<T>();

    //methods to fulfil List interface contract...

    @Override
    public T get(int index) {
        T t = backingList.get(index);
        return makeCopy(t);
    }

    private T makeCopy(T t) {
        //make a copy of t!
    }
}

正因为如此,如果get(int)方法将返回副本,我们无法判断(如果没有告诉我们基础类型)。

答案 2 :(得分:1)

它引用列表中的实际项目,所有强制转换都告诉编译器忽略声明的类型,你知道对象的实际类型是什么成为。 (但是如果你错了,你会得到一个ClassCastException运行时,这就是为什么在可能的情况下应该避免转换的原因。没有详细说明,泛型可以帮助解决这个问题。)

现在,这种事情(修改集合的元素)可以使用列表而不会出现问题但使用Set s并且对于Map的键,您必须使用不可变对象(基本上是对象的字段)调用构造函数后无法更改),否则可能会造成正确的混乱。如果您的集合在多个线程之间共享,您也应该避免这种情况。

答案 3 :(得分:0)

如果使用泛型,则不需要强制转换,否则需要进行强制转换,因为无法知道对象列表的类型。

但我想知道如何在编译时处理它 - 演员是否会创建一个新对象

编译器不会创建任何对象。它只是检查语法和语义。编译该特定行时,编译器知道引用是类型DataObject,但list.get()返回导致不兼容类型的对象类型。所以,你需要明确地施放。

答案 4 :(得分:0)

强制转换不会创建新的DataObject。在将基元转换为包装类型时,转换通常不会创建新对象,除了,或者对String进行显式或隐含转换,从而导致调用toString()方法。

答案 5 :(得分:0)

myList.get()可以定义为返回更通用的类型,例如Object。您不能使引用变量引用比其本身更通用的类型。因此,你必须做演员 -

DataObject myItem = (DataObject) myList.get(i);

演员表不会创建新对象。强制转换只会使变量myItem引用列表中已存在的对象。因此,setString()方法会更改您的实际对象。因此,列表中的对象也会更改,因为它是同一个对象。

答案 6 :(得分:0)

如果myList被声明为类型列表,则如下:

List<DataObject> myList = new ArrayList<DataObject>();

然后不需要演员。但是,如果它是无类型List,则其get方法将返回类型为Object的对象。这可能就是为什么演员是必要的(没有看到声明,我无法分辨)。

话虽如此,演员表并没有创建新对象,所以你得到的是对列表中已经存在的对象的新引用。这意味着任何修改都在myList内发生。

答案 7 :(得分:0)

它可能是同一个对象。

创建new对象的唯一方法是 - 什么? new关键字。有些人声称clone()创建了一个新对象(如果正确实现了),但是我猜怎么着?在克隆函数中,某处有new个关键字!

现在,我不知道你正在处理什么样的myList,但假设它是标准Java库(ArrayList, LinkedList, etc)的一部分,那么你得到相同的对象。

P.S。请记住,数组也是对象!