• Post Reply Bookmark Topic Watch Topic
  • New Topic

object reference  RSS feed

 
ben oliver
Ranch Hand
Posts: 375
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If I have a object of class type "SalesOrder". This class can include lot of attributes like string, double, array[], reference to other objects, etc.

If I do



what I want to do is -- First I need to put "order" object into map, then I need to retrieve it out and make some change and put it back using a different key. But by doing this way, I think I am also altering the original "order" object so next time when I do map.get("john") I would get a different object, which is NOT what I want. I want to keep the value for key of "john", take it out, maybe create another duplicated one and change on that new one and put it into map with a new key.

but I just don't know how. Any help ?
 
ryan sukale
Ranch Hand
Posts: 53
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Ben,

As you would have already noticed, objects are stored as references.
When you do a map.get() you get a reference to the object that was stored in the map.
When you manipulate the object, you are in fact, manpulating the original object.

When you again store this object using the map.put('mark', order2), you are storing the reference to the original object in the map.

Both, the keys - john and mark store a reference to the same sales order object in the map. You dont have 2 objects.

What you actually want to do is to create a copy of the object.

You may want to do this by creating a new constructor in the SalesOrder class that accepts another sales order object and copies all the attributes of the argument to its own instance variables.




What you actually want to do is a deep copy of the 'orderToCopy'. However there is no simple solution to doing a deep copy in java.

One way would be to use serialization, that is, hoping that your SalesOrder class implements the serializable interface.



IMO, copying the object via the overloaded constructor is a pretty neat way to do this as it gives you a clear indication of what is being copied and what not.
The downside is that you would have to copy each primitive value for the nested objects in the SalesOrder(the way we copied each primitive in the array) and not mistakenly assign references to the original object's instance variables.

I hope this helps or at least gives you a hint for the approach you might have to take.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
ben oliver wrote:what I want to do is -- First I need to put "order" object into map, then I need to retrieve it out and make some change and put it back using a different key.

Seems odd, but OK.
But by doing this way, I think I am also altering the original "order" object

You are.
so next time when I do map.get("john") I would get a different object, which is NOT what I want.

Actually, as ryan explained, you'd get the same object, except it would be changed; which is almost certainly not what you want.
I want to keep the value for key of "john", take it out, maybe create another duplicated one and change on that new one and put it into map with a new key.

but I just don't know how. Any help ?

There are several possibilities, of which ryan's is just one (and not my favourite, I have to admit).
A couple of others are:
1. If your Salesman class implements the Cloneable interface, use its clone() method.
2. (my slight preference) Have your Salesman class implement a copy constructor (or factory).

And just a general note: It's usually very bad practise to change fields that are used as keys.
If you think about it, your
map.put("john", order);
line could probably have been written as
map.put(order.getSalesName(), order);
which may make it clearer why you probably don't want to change the name.

HIH

Winston
 
dennis deems
Ranch Hand
Posts: 808
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It sounds like perhaps what you want is a Map<String, Map<String, SalesOrder>> so that with the key "john" you can get the map of all of John's orders, and then from that map get the particular SalesOrder you want to work with by its identifier.
 
ben oliver
Ranch Hand
Posts: 375
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks so much for the reply. I like the idea of doing straightforward copying attributes into a new object using the constructor method. Just want to confirm a stupid question --- If my "OrderDetails" class contains not only primitive type, but also some other class like "LineItem", "Contact" that each of themselves may be another class. Can I simply use ONE constructor like



When I create a new object , can I do



Question --

1. I don't need to worry how complex the "LineItem" is and just need to do the above, correct ?
2. Does "order" object's "item" points to the same object "anotherOrder" object's "item" ? That scares me most.

thanks.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
ben oliver wrote:
1. I don't need to worry how complex the "LineItem" is and just need to do the above, correct ?


That depends on your specific requirements, in particular, as they relate to the answer for #2.

2. Does "order" object's "item" points to the same object "anotherOrder" object's "item" ? That scares me most.


If you don't take explicit steps to create distinct object for the new "item" to point to, then, yes, it points to the same as the original.



We now have 2 order objects, and 1 Item object, and both orders' item fields are pointing to that one Item object. If your Item class has a similar copy constructor, then you can do


and so on for each mutable object field that Item contains, and on down the layers.

In other words, if you don't explicitly make a deep copy, you'll just get a shallow copy, since assignment in Java (using the = operator) just copies references, never objects.

Note that you don't need to deep copy members in the following cases.

  • The member is a primitive.
  • The member is an immutable class such as String, Integer, etc.
  • You don't care if the original and the copy see the same changes deeper down, or you explicitly WANT them to see them.
  •  
    Winston Gutkowski
    Bartender
    Posts: 10575
    66
    Eclipse IDE Hibernate Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    ben oliver wrote:Thanks so much for the reply...

    I split a couple of your enormously long lines; it was causing windowing problems.

    As to your problem: as Jeff says, it depends on what your requirements are. If you need a truly "deep" copy, then you have to apply the same logic to any component in your object that you do to the object itself (you might want to Google "Java object graph"). That said, the need for deep copies is relatively rare.

    Winston
     
    dennis deems
    Ranch Hand
    Posts: 808
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    For this use case I think a Factory makes better sense than a copy constructor. Use of a copy constructor really ought to be limited to cases in which we really do want an honest-to-goodness copy.
     
    Jeff Verdegan
    Bartender
    Posts: 6109
    6
    Android IntelliJ IDE Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Dennis Deems wrote:For this use case I think a Factory makes better sense than a copy constructor. Use of a copy constructor really ought to be limited to cases in which we really do want an honest-to-goodness copy.


    Sorry, not following. What exactly is an "honest to goodness copy" and how is it different from what the OP wants?

    And why is a copy constructor inferior to a copy factory method in the OP's case?

     
    ben oliver
    Ranch Hand
    Posts: 375
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I forgot to say " Thank you Jeff !"
     
    Jeff Verdegan
    Bartender
    Posts: 6109
    6
    Android IntelliJ IDE Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    ben oliver wrote:I forgot to say " Thank you Jeff !"

    You're welcome.
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!