While I have been programming for years, I am new to Java. I have run into a problem with HashMaps that I'm not sure how to resolve. I thought I searched this site pretty well, but I must not be using the right terms, as I don't think I am the first person to run into this problem. I have to believe there is a simple solution I am just not seeing (forest for the trees).
I have a program that uses HashMaps to pass around a lot of variables back and forth between classes. This was done because we are interfacing various systems contain non-harmonious data that we are trying to process within the program.
What I discovered, after much hair pulling (not that I had much to begin with), is that when a HashMap is "returned" by a method in a class, the values are not returned to the calling class's procedure. Rather a pointer to HashMap in the "called" class procedure is returned. Subsequent modifications to a "copy" of HashMap in the "calling" class's method are reflected in the called class's HashMap even though the called class's HashMap is marked private (and the classes are in different packages!).
Likewise, any modifications to the "called class's HashMap" are also reflected in the calling class's HashMap.
Confused? So was I, so I boiled it all down to small bit of code that reproduces what I found. (It can probably be shorten even more but I was trying to preserve some of the levels I am using.)
TMain.java - default package:
import mainLogic.MainLogic; public class TMain { private static MainLogic ml = new MainLogic(); public static void main(String[] args) { ml.performMainLogic(); } }
MainLogic.java - the "calling class"
package mainLogic; import java.util.HashMap; import subLogic.SubLogic; public class MainLogic { private HashMap<String,String> slValues; public MainLogic() { // do constructor stuff here } public void performMainLogic(){ SubLogic sl = new SubLogic(); sl.performSubLogic(); // returns pointer rather than values? slValues = sl.getSLHashUser(); showSLValues("MainLogic - after calling sl.getSLHashUSer"); sl.showSLHashUser("MainLogic - calling sl.showSLHashUserafter calling sl.getSLHashUser"); // affects both slValues AND slHash in the SubLogic Class!!!!! slValues.put(SubLogic.USER_FLD1,"NEWVALUE"); showSLValues("MainLogic - slValues after put"); sl.showSLHashUser("MainLogic - calling SubLogic showSLHashUser after slValues put"); // modifies slHash in SubLogic Class AND slValues here!!!!! sl.doSubLogic2(); showSLValues("MainLogic - slValues after doSubLogic2"); sl.showSLHashUser("MainLogic - calling SubLogic showSLHashUser after doSubLogic2"); } public void showSLValues(String title) { System.out.println(title); System.out.println(" slValues"); System.out.println(" Field 1 :\t" + slValues.get(SubLogic.USER_FLD1) ); System.out.println(" Field 2 :\t" + slValues.get(SubLogic.USER_FLD2) ); System.out.println(""); } }
SubLogic - the "called class"
package subLogic; import java.util.HashMap; public class SubLogic { private HashMap<String,String> slHashUser = new HashMap<String, String>(); // field names slHashUser static public final String USER_FLD1 = "ONE"; static public final String USER_FLD2 = "TWO"; public SubLogic() { slHashUser.put(USER_FLD1, "SubLogic1"); slHashUser.put(USER_FLD2, "SubLogic2"); showSLHashUser("SubLogic - Constructor"); } public void performSubLogic(){ slHashUser.put(USER_FLD1, "PSubLogic1"); slHashUser.put(USER_FLD2, "PSubLogic2"); showSLHashUser("SubLogic - performSubLogic"); } public void doSubLogic2(){ slHashUser.put(USER_FLD1, "modified"); showSLHashUser("SubLogic - doSubLogic"); } public HashMap<String,String> getSLHashUser() { showSLHashUser("SubLogic - getSubLogic"); return slHashUser; } public void showSLHashUser(String title) { System.out.println(title); System.out.println(" slHash Values"); System.out.println(" Field 1 :\t" + slHashUser.get(USER_FLD1) ); System.out.println(" Field 2 :\t" + slHashUser.get(USER_FLD2) ); System.out.println(""); } }
My first thought is that I need do something different in MainLogic at the line:
slValues = sl.getSLHashUser();
but I wasn't sure if the real problem was in SubLogic's getSLHashuser method where I tried to do the return:
return slHashUser;
Since java is supposed to be all about "passing by value" and "pass by reference" (in the old school "C" sense), I just wasn't expecting this.
Your help will be appreciated, even if it is a pointer to the correct documentation that I must have overlooked.