sravanreddy001
sravanreddy001

Reputation: 257

Returned object modification java

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

Answers (4)

Bohemian
Bohemian

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

Greg Kopff
Greg Kopff

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

Tim Bender
Tim Bender

Reputation: 20442

As others have mention, the answer is Yes.

An option not yet mentioned is to make the Node object immutable.

Upvotes: 0

Wyzard
Wyzard

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

Related Questions