3

I have a doubt about object references in Java. It always send its object by reference to the functions, and it means that if you modifie them in the function sent, they will come back modified.

A solution for this would be copying the object before the send. But for that, do I have to create a copy function in the object class? Or is any other alternative? Thanks

millimoose
  • 39,073
  • 9
  • 82
  • 134
Frion3L
  • 1,502
  • 4
  • 24
  • 34
  • 7
    _It always send its object by reference to the functions_ No, it sends a copy of the value of the reference. – Sotirios Delimanolis May 15 '13 at 14:26
  • There's no easy solution for this. Have a look at explanation of immutable objects in java: http://www.javapractices.com/topic/TopicAction.do?Id=29 If you want your objects to be immutable, you have to program the behavior yourself. – NeplatnyUdaj May 15 '13 at 14:26
  • There is a reason that objects are passed by reference, your code should not try to modify this behavior, but use it to your advantage. Do you have an example of code that needs to send a copy of an object? – BLuFeNiX May 15 '13 at 14:27
  • @BLuFeNiX Objects are not passed by reference. – Sotirios Delimanolis May 15 '13 at 14:27
  • @Sotirios Delimanolis In Java anything that is an Object and not a primitive type is a reference – Menelaos May 15 '13 at 14:28
  • @meewoK I agree with that point, but when you use an Object as an argument to a method, it is passed by value. – Sotirios Delimanolis May 15 '13 at 14:29
  • @SotiriosDelimanolis: I don't think you know what "pass by value" and "pass by reference" mean. – BLuFeNiX May 15 '13 at 14:30
  • A common misunderstanding is that java is *Pass by Reference* when in fact it's always *Pass by value*. You pass the value of a field or, in the case of an object, you pass the value of the reference. – Fritz May 15 '13 at 14:30
  • 1
    @BLuFeNiX You should read: http://stackoverflow.com/questions/40480/is-java-pass-by-reference – Sotirios Delimanolis May 15 '13 at 14:31
  • @BLuFeNiX The problem lies in confusing terminology. "pass-by-reference" means "pass a reference to a local variable / lvalue in the calling method" - what the `&` operator does in C++. However, Java also calls the values of object-typed variables "references". When you pass an *object reference* around in Java, you're passing the value of that object reference. You cannot however pass, say, a reference to a local variable `foo` in the calling function (or say to a field of the object the calling function is in), and have the called function change the value of that variable. – millimoose May 15 '13 at 14:32
  • @BLuFeNiX It's probably easier to think about this if you use the term "object handle" instead of "object reference" when discussing this, then it becomes a little less unclear what it means to say Java is *pass-by-value*. But the **tl;dr** version is the meaning of the word "reference" is different in the phrases *pass-by-reference* and *object reference*. – millimoose May 15 '13 at 14:34
  • @BLuFeNiX you are wrong. SotiriosDelimanolis is right. – NimChimpsky May 15 '13 at 14:34
  • @SotiriosDelimanolis, Yes, I understand that, but passing the value of a reference is essentially the same as passing by reference. – BLuFeNiX May 15 '13 at 14:36
  • @millimoose Indeed. You could even use a sort of metaphor by saying that objects could be tought of as "pointers" and, by passing it as a parameter, you actually pass the *value* of the chunk of memory that "pointer" points to. – Fritz May 15 '13 at 14:36
  • @BLuFeNiX its not, what happens when you overwrite it ? – NimChimpsky May 15 '13 at 14:37
  • @BLuFeNiX Wrong, I think the concept is different. If you passed the reference in a method and you did `param = someOtherObject` your parameter would end up being a completely different object. – Fritz May 15 '13 at 14:38
  • 2
    @BLuFeNiX **No it is not the same.** *Passing-by-reference* means you can change the values of *local variables* or *fields* in the calling context, because you pass a reference to those memory locations. (And not to an object that has those fields, that "doesn't count".) This is something you cannot do in Java, while it's easily possible in C, C++, and I think PHP. *Pass-by-reference* means you have to be able to pass an *lvalue* to a called function, if that helps clear things up. In Java, you can only pass (possibly mutable) *rvalues*. – millimoose May 15 '13 at 14:38
  • 1
    Well, you learn something new every day. – BLuFeNiX May 15 '13 at 14:46

4 Answers4

3

I typically add a copy constructor for this kind of scenario like so:

public class MyObject {
    //members


    public MyObject(MyObject objectToCopy) {
       this.member = objectToCopy.member;
       //...
    }
}

Then you can just make a new object with a simple one liner.

public void DoWork(MyObject object) {
    MyObject copy = new MyObject(object);
    //do stuff
}
Matthew Cox
  • 13,566
  • 9
  • 54
  • 72
  • 1
    Isn't the best practice is to implement clone? – danieln May 15 '13 at 14:38
  • 1
    -1: Sorry to say, but this is the wrong way to copy/clone an object. More info: [Java: recommended solution for deep cloning/copying an instance](http://stackoverflow.com/q/2156120/1065197) – Luiggi Mendoza May 15 '13 at 14:45
  • this results in very messy code for more complex objects. I will not suggest to copy like this. – Vegard May 15 '13 at 14:50
  • @Vengard For complex objects I might agree with you but using a sledge hammer to drive a nail is silly. Simple objects can use simple approaches that are more efficient that reflection – Matthew Cox May 15 '13 at 14:55
  • @LuiggiMendoza I would say the same to you that I did to Vengard ... plus, any usage of reflection comes at even more of a performance cost that shouldn't be overlooked – Matthew Cox May 15 '13 at 14:56
  • When you have to *clone* simple objects it comes a question: why would you need that? And probably you will come with a design problem instead of copying the object at all, and probably your *simple* class must be immutable to avoid these problems. – Luiggi Mendoza May 15 '13 at 15:02
  • @FeistyMango I usually try to avoid to copy objects in Java all together, at least if the code is performance sensitive. But if I really have to, which is not very often, I use frameworks such as Dozer. it comes with a very small cost, negligible for most scenarios. http://dozer.sourceforge.net/documentation/faq.html#dozer-perf – Vegard May 15 '13 at 15:05
3

Java is always pass-by-value. What you are describing is passing the object reference by value.

There is a key distinction here. You are not passing the object as a reference, so the reference link is broken as soon as you assign a new instance to your parameter. As long as the reference value remains the same, altering the contents of an object passed in will persist when you return back to the caller. Another key difference is that a reference value can be null... but null is not an object - so how can you reference the absence of an object?

If you want to create a new object, you will need to copy the existing one. The copy should be performed inside the method to ensure the operation is consistent.

For simple objects (objects with a shallow class hierarchy, like the example below), you can usually get by with a basic copy constructor:

class Album {
  private String title;
  private String artist;

  public Album(Album copy) {
    this.title = copy.title;
    this.artist = copy.artist;  
  }
}

This will allow you to copy the object inside your method:

public void copyAlbum(Album album) {
    album = new Album(album); // Clone the album passed in
}

For more complex object graphs, you may want to use a library such as Orika or Dozer to accurately create a deep copy of your object. This question has some useful advice on copying objects in Java.

Community
  • 1
  • 1
seanhodges
  • 17,426
  • 15
  • 71
  • 93
  • +1 for the first sentence. – Fritz May 15 '13 at 14:44
  • 1
    Your answer was good **until** you wrote that example to clone objects... – Luiggi Mendoza May 15 '13 at 14:46
  • Please define *simple* classes (not objects since an object is an instance of a class). – Luiggi Mendoza May 15 '13 at 14:48
  • Ah, the age-old war on the dangers of copy constructors! I disagree, copying an object by hand is by far the safest way to ensure it has been done correctly. Cloning tools are helpful in certain contexts, but you must use the right tool for the job. I've seen far more bad examples of object cloning with a misconfigured Dozer than I have with the traditional copy constructor approach. – seanhodges May 15 '13 at 15:06
1

You should create a copy constructor for each object yourself. The reason is simple: if A references B and you want to copy A, would you copy the reference to B or the whole referenced B object? This question must be answered for each case individually, so there is no general solution.

Bartosz Marcinkowski
  • 6,651
  • 4
  • 39
  • 69
1

It is true that you send the object, and changes will be done to the referenced object. There is no easy "native" way to copy objects in Java, but you can copy objects by using frameworks such as Dozer:

http://dozer.sourceforge.net/

Vegard
  • 1,802
  • 2
  • 21
  • 34