2012-03-29 84 views
0

上Java基础的一些问题, 以下函数返回节点类型的对象预先返回的对象修改的java

class DS{ 
    public Node getNode(int index){ 
     return nodeList.get(index); 
    } 
} 

public void test1(){ 
    DS ds = new DS(); 
    Node node = ds.getNode(3); 
    // will the change in node variable(of test1()) change the actual Node object in ds? 
    // Is there a simple way to create a copy to prevent source node's data modification? 
} 

感谢。

回答

2

DS类的getNode()方法返回参考到存储在nodeList中的节点。因此,如果您的Node类可以进行变异(通过setter方法或直接访问其字段),那么是的,test1中的代码将更改底层(现在是共享的)节点引用。

如果你想“断开”返回的从节点的节点在数据存储,那么你可以先clone它。您的节点类将需要实现Cloneable并覆盖clone()方法。如果您在节点只图元,那么你可以简单地做:

public Object clone() 
{ 
    return super.clone(); 
} 

如果在节点的其他对象,那么默认的克隆操作只会让浅拷贝,你将需要使你的克隆方法更广泛,以至于它使深拷贝。从Object.clone()的Javadoc:

按照惯例,此方法返回的对象应该独立于此对象(正在克隆)。为了实现这种独立性,可能有必要在返回之前修改super.clone返回的对象的一个​​或多个字段。通常,这意味着复制包含被克隆对象的内部“深层结构”的任何可变对象,并将这些对象的引用替换为对这些副本的引用。如果一个类只包含原始字段或对不可变对象的引用,那么通常情况下,super.clone返回的对象中的字段不需要修改。

您的DS类的变化将是:

public Node getNode(int index){ 
    return (Node) nodeList.get(index).clone(); 
} 
1

是的,修改test1()中的node将修改ds列表中的对象。这是因为它是对同一个对象的引用。

如果要修改node而不影响原始文件,则需要复制 - 例如,执行new Node(),然后将所有字段从旧的复制到新的。您也可以实现Cloneable接口并使用Object类提供的clone()方法。或者给Node一个构造函数,它将另一个Node作为参数并复制其数据。

+0

仅供参考,接受同一类型的另一个对象,并创建一个副本从它(不出所料)“拷贝给一个构造函数的名称构造函数“ – Bohemian 2012-03-29 01:35:59

+0

现有的默认克隆方法不够吗? 我应该明确实施吗? – sravanreddy001 2012-03-29 01:39:32

+1

@mrb - 如果你在一个没有实现'Cloneable'的对象上调用clone(),你会得到一个'CloneNotSupportedException'。参考:用于'Cloneable'的javadocs。 – 2012-03-29 01:46:48

0

是的。您只需将引用添加到(相同)节点对象。任何改变都会反映出来(尽管有线程问题)。

要返回节点的副本代替,这样做:

创建一个“拷贝构造函数”:

public Node(Node node) { 
    // Copy all the fields across 
    this.field1 = node.field1; 
    this.field2 = node.field2; 
    // etc 
} 

从你的方法,使用拷贝构造函数返回一个副本:

public Node getNode(int index){ 
    return new Node(nodeList.get(index)); 
} 

此代码模式被称为“安全发布” - 你的API安全提供对象给调用者,你的类是ACCID安全对其状态进行修改(即字段)。

+0

我可以做什么来创建一个不同的对象来返回? – sravanreddy001 2012-03-29 01:37:14

+0

我会*不*使用'可克隆'。我只是简单地制作一个拷贝构造函数 - 参见编辑答案 – Bohemian 2012-03-29 22:48:09

0

正如其他人提到的,答案是肯定的。

没有提到的一个选项是使Node对象immutable

+0

它并不是我不想进行更改, 我想进行更改,但我需要一份不是原创的副本。因此,如果我们不使用新的关键字(某些地方在代码中),它只是对该对象的引用。它是否正确? – sravanreddy001 2012-03-29 01:41:05