【问题标题】:Java method returning object or directly manipulate it?Java方法返回对象还是直接操作它?
【发布时间】:2016-06-08 19:19:06
【问题描述】:

我遇到了这段(对我来说很奇怪)代码。实际上,我从未见过它被使用过,我自己也从未使用过它,所以这很令人困惑......这与

  • 此处使用 hashmap 作为示例,但其他对象的行为相同
public static void fillData(HashMap<Object, Object> dataMap){
    dataMap.put("key","value");
}

现在这很令人困惑,因为我了解到你这样做的方式更像这样

public static HashMap<Object, Object> fillData(){
    HashMap<Object, Object> dataMap = new HashMap<>();
    dataMap.put("key","value");
    return dataMap;
}

现在有没有时候我应该使用一种方式或另一种方式?我对编程还是很陌生,但我还没有发现很多关于这种结构的东西。

我也进行了实验,发现这只适用于对象,而不适用于原语......

【问题讨论】:

  • 一般来说你应该尽量避免修改参数,但在某些情况下这是不可能的。
  • 这个问题和答案也可能会有所帮助:stackoverflow.com/questions/7931523/…
  • 顺便说一句:原语是按值传递的,因此您仅在对调用方没有影响的方法中操作副本。

标签: java methods return


【解决方案1】:

好吧,考虑一下该方法操作现有非空地图的情况。在这种情况下,第一个示例非常有意义。

【讨论】:

    【解决方案2】:

    早上我在谷歌上搜索同样的主题,发现 this discussion,它指出第一种形式

    public static void fillData(HashMap<Object, Object> dataMap){
        dataMap.put("key","value");
    }
    

    被认为是“一种不好的做法,退化的或 OOP 之前的时代。”

    【讨论】:

      【解决方案3】:

      在 java 中,方法参数不是原始的持有对对象的引用。 在你的例子中

      public static void fillData(HashMap<Object, Object> dataMap){
          dataMap.put("key","value");
      }
      

      dataMap 引用一个对象,并且对该对象的任何更改都会影响显示该对象的整个系统引用。

      例如;

      public static void fillAll(){
              HashMap<Object, Object> dataMap1 = new HashMap<>();
              HashMap<Object, Object> dataMap2 = dataMap;
              HashMap<Object, Object> dataMap3 = dataMap;
              //dataMap1, dataMap2, dataMap3 are same object's references.
              fillData1(dataMap1);
              fillData2(dataMap2);
              fillData3(dataMap3);
              //here dataMap1 holds 3 different values in it.
              //dataMap2, dataMap3 still same as dataMap1 
              dataMap3 = new HashMap<>();
              //here dataMap3 have a new object's reference but dataMap1 and dataMap2 still have 3 values in the map object.
              //primitive types are different they are holding values directly.
              int x = 5;
              int y = x;
              x++; //now x value is 6 but y value is still 5
      }
      
      public static void fillData1(HashMap<Object, Object> dataMap){
          dataMap.put("key1","value1");
      }
      
      public static void fillData2(HashMap<Object, Object> dataMap){
          dataMap.put("key2","value2");
      }
      
      public static void fillData3(HashMap<Object, Object> dataMap){
          dataMap.put("key3","value3");
      }
      

      【讨论】:

        【解决方案4】:

        我遵循的做法基于两种情况:

        场景 1. 如果调用方法对传递给方法的复杂对象进行更改,那么修改传递的对象并从方法中不返回任何内容 (void) 会更有意义。对象在 java 中是按值传递的(这里的“值”是指复制和传递的对象引用信息),因此任何修改都会更新对象的主副本,并且不需要从方法返回任何内容。

        场景 2. 如果调用方法利用传递的复杂对象,运行一些逻辑并准备另一种类型的复杂对象,那么从方法中创建并返回这个新对象是有意义的。

        回到你的问题 - 它是一个静态方法,因此它的实例独立。我又可以想到两种可能的情况:

        场景 1- 如果您的“dataMap”可以在此方法调用之前启动,并且它可能已经有一些其他键值对,那么传递这个“dataMap”并让该方法更新这个带有附加的同一个映射会更简单键值对。在这种情况下不会返回任何东西。

        场景 2- 如果您的“dataMap”在此方法调用之前始终应该是一个新的空地图,那么我看不出有任何理由创建 Map 实例并将其传递给方法。如果该方法创建此映射并作为方法返回参数返回,则代码行数将更少且更简单。

        根据给定的场景,这两种方法都有其适用性,我不会说其中一种比另一种更好。

        【讨论】:

          【解决方案5】:

          让我们看看这些 API 的用法(将 HashMap 替换为 Map,使用接口而不是具体实现总是更好):

          Map<Object, Object> data = new Map<>();
          fillData(data);
          

          这种通过参数创建的副作用代码在 API 中是不可见的。所以最好让方法返回结果,这样也可以变得更流畅:

          Map<Object, Object> data = fillData(new HashMap<>());
          

          如果之前的 map 中有“key”的值,会发生什么?会不会被替换?该方法还可以通过返回原始地图的副本来消除副作用:

          public static Map<Object, Object> filledData(Map<Object, Object> original) {
              Map<Object, Object> result = new HashMap<>(original);
              result.put("key","value");
              return result;
          }
          

          函数式方法独立于初始状态:

          Map<Object, Object> data = createFilledData();
          

          一如既往,使用什么取决于要求。这是公共 API 还是内部辅助方法?谁会使用它,新手还是专家?性能怎么样?

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-11
            • 1970-01-01
            • 2016-06-21
            • 2014-09-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多