虽然我已经编程多年,但我是Java的新手。我遇到了HashMaps的问题,我不确定如何解决。我以为我搜索过这个网站很好,但我不能使用正确的条款,因为我不认为我是第一个遇到这个问题的人。我不得不相信有一个简单的解决方案,我只是没有看到(森林为树木)。
我有一个使用HashMaps在类之间来回传递大量变量的程序。这样做是因为我们正在连接各种系统,其中包含我们正在尝试在程序中处理的非和谐数据。
我发现,经过大量的头发拉动(不是我开始的很多),是当HashMap被"返回"通过类中的方法,值不会返回到调用类的过程。而是指向"中的HashMap指针"返回类过程。对"副本"的后续修改HashMap在"调用" class的方法反映在被调用类的HashMap中,即使被调用类的HashMap被标记为private(并且这些类在不同的包中!)。
同样,对"被称为类的HashMap"的任何修改。也反映在调用类的HashMap中。
困惑?我也是如此,所以我把它全部归结为一小部分代码,再现了我发现的东西。 (它可能会缩短甚至更多,但我试图保留我正在使用的一些级别。)
TMain.java - 默认包:
import mainLogic.MainLogic;
public class TMain {
private static MainLogic ml = new MainLogic();
public static void main(String[] args) {
ml.performMainLogic();
}
}
MainLogic.java - "调用类"
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 - &#34;名为class&#34;
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("");
}
}
我首先想到的是,我需要在MainLogic中做一些不同的事情:
slValues = sl.getSLHashUser();
但是我不确定真正的问题是否在SubLogic的getSLHashuser方法中,我试图做返回:
return slHashUser;
因为java应该是关于&#34;传递值&#34;并且&#34;通过引用传递&#34; (在旧学校&#34; C&#34;感觉),我只是没想到这一点。
即使是指向我必须忽略的正确文档的指针,我们也将不胜感激。
答案 0 :(得分:2)
&#34;困惑&#34;
没有。这是可变对象在Java中的工作方式。
因为java应该是关于&#34;传递值&#34;并且&#34;通过引用传递&#34; (在旧学校&#34; C&#34;感觉),我只是没想到这一点。
Java方法参数和结果完全传递值。
然而,很多新手都错过了一个微妙之处。当您传递或返回一个对象时,它是传递和复制的对象引用 ...而不是对象本身的状态。
但是如果你记住那个微妙的观点,你观察到的是既可以解释又是自然的。
如果您的应用程序要求在返回HashMap时进行复制,则需要明确进行复制。幸运的是,HashMap
有一个&#34;复制构造函数&#34;它产生一个新的HashMap
,它是现有Map状态的浅表副本。
答案 1 :(得分:1)
当一个方法返回对一个可变对象的引用时,该方法的调用者可以通过调用该引用的方法来改变该对象,从而改变调用该方法的对象的状态。
为防止此类修改,您可以返回HashMap
:
public HashMap<String,String> getSLHashUser() {
showSLHashUser("SubLogic - getSubLogic");
return new HashMap<String,String>(slHashUser);
}
这样,更改返回的HashMap不会影响slHashUser
成员的内容。