0

Example Code :

Main Program :

package com.company.reference;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Reference {
    public static void main (String arga[]) {
        List<Map<String,Data>> listOfMaps = new ArrayList<Map<String, Data>>();
        Map<String, Data> m0 = new HashMap<String, Data>();
        m0.put("userLines", new Data("amy", "strachan"));
        Map<String, Data> m1 = new HashMap<String, Data>();
        m1.put("userLines", new Data("amy", "strachan"));

        listOfMaps.add(m0); listOfMaps.add(m1);
        for (Map<String,Data> m3 : listOfMaps) {
            System.out.println(m3);
        }


        List<Document> docs = new ArrayList<Document>();
        for (int i = 0; i < 2; i++) {
            Line line = new Line();
            line.setDayOfWeek(DayOfWeek.MON);
            line.setActivity("1");
            Map<enumUser, Line> m = new HashMap<enumUser, Line>();
            m.put(enumUser.USER, line);

            Document doc = new Document();
            int docId = i;
            doc.setId(docId);
            doc.setUserLines(m);
            docs.add(doc);
        }

        int cnt = 0;
        for (Document document : docs) {
            System.out.println(document.getUserLines());
            document.getUserLines().get(enumUser.USER).setActivity("foo" + cnt);
            System.out.println(document.getUserLines());
            cnt++;
        }
    }
}

Example Output :

{a=com.company.reference.Data@30c3bb57}
{a=com.company.reference.Data@4402083d}
{U=com.company.reference.B@bb56a086}
{U=com.company.reference.B@bb86ac7f}
{U=com.company.reference.B@bb56a086}
{U=com.company.reference.B@bb86ac80}

Looking at the example output :

a) Line 1 and Line 2 have different references.
b) Line 3 and Line 5 have the same reference, Line 4 and Line 6 have different references.

Question :

  1. Why do Line 3 and Line 5 have the same reference? Shouldnt they essentially emulate the behavior of Line 1 and Line 2.
  2. How did the Java runtime, separate the references in Line 4 and Line 6. That is, if there was an optimization done, how come the runtime was able to separate them once the internal values were different.
  3. If the Java runtime optimized Line 3 and Line 5, why did it not do the same for Line 1 and Line 2.

I actually observed the behavior in Lines 3 to Lines 6 in a real program. I attempted to replicate using a small program and was successful, but it created more questions in the process.

Krish Srinivasan
  • 568
  • 1
  • 6
  • 14
  • 1
    Optimization isn't going to have anything to do with this. I'm still trying to disentangle the messy code, but I expect you're expecting a copy to happen when it doesn't. – Louis Wasserman Mar 06 '14 at 19:45
  • 1
    How about some meaningful variable names? B a = new B() a.setC() .. a.setS() who are you trying to confuse? – Mark W Mar 06 '14 at 19:50
  • 5
    WTF... ´B a = new B(); a.setC(C.A);´? Are you kidding? Is that code obfuscated? :D – Thomas Uhrig Mar 06 '14 at 19:50
  • 1
    @ThomasUhrig don't forget about `d.getA().get(A.U).setS` – matt b Mar 06 '14 at 19:58
  • 1
    This is seriously unreadable. You can make a much simpler test with `Object` objects. The thing you need to understand is that `hashCode()` doesn't necessarily return the address location of an object. – Sotirios Delimanolis Mar 06 '14 at 19:59
  • The real code is too long. I will try to make it clearer. – Krish Srinivasan Mar 06 '14 at 20:05
  • @Thomas - No, not obfuscated, just bad use of the IDE's refactor to turn class names in single letters. – Krish Srinivasan Mar 06 '14 at 20:06
  • @Sotirios - I dont understand what hasCode() has to do with this? – Krish Srinivasan Mar 06 '14 at 20:20
  • 1
    That's the result you are seeing in `com.company.reference.B@bb86ac80`. That's what seems to be confusing you. That result is not necessarily unique, nor is it representative of the value of a reference. – Sotirios Delimanolis Mar 06 '14 at 20:22
  • Furthermode, relying on the `hashCode()` of a mutable object is a big no-no. – biziclop Mar 06 '14 at 20:26
  • @Sotirios - that explains the behavior I am seeing. – Krish Srinivasan Mar 06 '14 at 20:28
  • 1
    If you really want to check references and object identity, use the `==` operator on the objects in question. But as a rule the JVM never "optimizes" different references into one or vice versa. However, individual implementations of `Map` or `Collection` might choose to return a copy of the object you put into them. [Persistent map](http://stackoverflow.com/questions/1536953/recommend-a-fast-scalable-persistent-map-java) implementations do this for example. Therefore it's best not to rely on object identity at all. – biziclop Mar 06 '14 at 20:35
  • @biziclop - yes, I think I will use the == instead. Unfortunately its not as visual as the print of the object, but the advantage is that it is more precise. – Krish Srinivasan Mar 06 '14 at 20:46

0 Answers0