return hashmap更改指针而不是返回值

时间:2015-05-17 09:13:55

标签: java hashmap

虽然我已经编程多年,但我是Java的新手。我遇到了HashMaps的问题,我不确定如何解决。我以为我搜索过这个网站很好,但我不能使用正确的条款,因为我不认为我是第一个遇到这个问题的人。我不得不相信有一个简单的解决方案,我只是没有看到(森林为树木)。

我有一个使用HashMaps在类之间来回传递大量变量的程序。这样做是因为我们正在连接各种系统,其中包含我们正在尝试在程序中处理的非和谐数据。

我发现,经过大量的头发拉动(不是我开始的很多),是当HashMap被"返回"通过类中的方法,值不会返回到调用类的过程。而是指向"中的HashMap指针"返回类过程。对"副本"的后续修改HashMap在"调用" class的方法反映在被调用类的HashMap中,即使被调用类的HashMap被标记为private(并且这些类在不同的包中!)。

同样,对"被称为类的HashMap"的任何修改。也反映在调用类的HashMap中。

困惑?我也是如此,所以我把它全部归结为一小部分代码,再现了我发现的东西。 (它可能会缩短甚至更多,但我试图保留我正在使用的一些级别。)

  1. TMain.java - 默认包:

    import mainLogic.MainLogic;
    
    public class TMain {
        private static MainLogic  ml = new MainLogic();
    
        public static  void  main(String[] args) { 
            ml.performMainLogic();
        }   
    }
    
  2. 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("");
        }
    }
    
  3. 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("");
       }
    }
    
  4. 我首先想到的是,我需要在MainLogic中做一些不同的事情:

        slValues = sl.getSLHashUser();
    

    但是我不确定真正的问题是否在SubLogic的getSLHashuser方法中,我试图做返回:

        return slHashUser;
    

    因为java应该是关于&#34;传递值&#34;并且&#34;通过引用传递&#34; (在旧学校&#34; C&#34;感觉),我只是没想到这一点。

    即使是指向我必须忽略的正确文档的指针,我们也将不胜感激。

2 个答案:

答案 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成员的内容。