Reputation: 257
Some question on java basics, the below function returns an object of Node type
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?
}
Thanks in advance.
Upvotes: 0
Views: 1797
Reputation: 425083
Yes. You will simply get a reference to the (same) Node object. Any changes made to it are reflected everywhere (threading issues notwithstanding).
To return a copy of the Node instead, do this:
Create a "copy constructor":
public Node(Node node) {
// Copy all the fields across
this.field1 = node.field1;
this.field2 = node.field2;
// etc
}
From your method, return a copy using the copy constructor:
public Node getNode(int index){
return new Node(nodeList.get(index));
}
This code pattern is called "safe publishing" - your API safely provides objects to the caller and your class is safe from accidental modification of its state (ie fields).
Upvotes: 0
Reputation: 16585
The getNode()
method on the DS class returns a reference to the node stored in nodeList
. As such, if your Node
class can be mutated (via setter methods or direct access to its fields), then yes, your code in test1
will change the underlying (and now shared) Node reference.
If you want to "disconnect" the returned node from the node in your datastore, then you can clone it first. Your node class will need to implement Cloneable
and override the clone()
method. If you have only primitives in Node, then you can simply do:
public Object clone()
{
return super.clone();
}
If you have other objects in Node, then the default clone operation will only make a shallow copy, and you will need to make your clone method more extensive so that it makes deep copies. From the Javadoc for Object.clone():
By convention, the object returned by this method should be independent of this object (which is being cloned). To achieve this independence, it may be necessary to modify one or more fields of the object returned by super.clone before returning it. Typically, this means copying any mutable objects that comprise the internal "deep structure" of the object being cloned and replacing the references to these objects with references to the copies. If a class contains only primitive fields or references to immutable objects, then it is usually the case that no fields in the object returned by super.clone need to be modified.
The change to your DS class will be:
public Node getNode(int index){
return (Node) nodeList.get(index).clone();
}
Upvotes: 2
Reputation: 20442
As others have mention, the answer is Yes.
An option not yet mentioned is to make the Node object immutable.
Upvotes: 0
Reputation: 34563
Yes, modifying the node
in test1()
will modify the object that's in ds
's list. That's because it's a reference to the same object.
If you want to modify node
without affecting the original, you need to make a copy — for example, do new Node()
and then copy all the fields from the old one to the new one. You could also implement the Cloneable
interface and use the clone()
method provided by the Object
class. Or give Node
a constructor that takes another Node
as an argument and copies its data.
Upvotes: 1