更改参考或返回参考

时间:2014-04-07 08:12:23

标签: java immutability mutable

这是什么意思?最容易通过代码显示

import java.util.Date;

public class Example {

  public static void main(String... args) {
    Date d1 = new Date(2014,4,7);
    Date d2 = new Date(2014,4,7);

    methodA(d1);
    System.out.println("Month of d1: " +d1.getMonth());

    d2 = methodB(d2);
    System.out.println("Month of d2: " +d2.getMonth());
  }

  public static void methodA(Date d) {
    d.setMonth(6);
  }

  public static Date methodB(Date d) {
    d.setMonth(6);
    return d;
  }

}

首先忽略已弃用的日期代码。在谈论像Date这样的可变对象时,最好如方法B那样进行更改并返回引用,还是可以使用methodA'

我怀疑方法B是大多数人会选择的但是为什么?

注意方法在使用可变对象时,只有与methodB相同的结果。例如,交换一个Integer的日期,并且在调用methodA之后,第一个对象的值将保持不变(假设methodA和methodB都对相同值的两个Integer引用执行简单的增量)

6 个答案:

答案 0 :(得分:3)

我更喜欢methodA,因为很明显你会修改我提供的参数。

我发现methodB在其当前形式中具有误导性,因为我认为该参数不会被修改,而实际上它将被修改。您可以随时编辑代码以消除这种误导行为:

public static Date methodB(Date d) {
  Date result = d.clone();
  result.setMonth(6);
  return result;
}

在某种程度上,methodB允许方法链接,但返回的对象本身就是参数的情况并不常见。更常见的情况是,返回的对象与您调用方法的类相同:

public class DateManipulator {

  public DateManipulator(Date d) {
    // store d
  }

  public static DateManipulator methodB() {
    d.setMonth(6);
    return this;
  }

  public static Date build() {
    return d;
  }
}

允许构造:

new DateManipulator(d).methodB().methodC()....build();

答案 1 :(得分:0)

大多数人都赞成选项2,因为它支持链接

Example.methodB(...).someThing()

但是,如果方法可以返回一些其他信息,则应该不惜一切代价避免使用此方法(一个常见示例是返回指示方法成功或失败的布尔值)。

常见示例是StringBuilder类。 StringBuilder.append()返回一个StringBuilder(this),因此您可以链接append()个命令。

请注意,此方法通常用于调用对象(如StringBuilder示例),但参数变量也非常好。

答案 2 :(得分:0)

一般我更喜欢methodA,因为我会考虑返回另一个对象,暗示原始版本未被修改。所有String处理方法都是示例。

但是,有一些特殊情况,例如构建器模式,其中methodB的工作原理很清楚,并且您可以链接调用。可能需要消费者知道构建器模式,因此methodB在这种情况下不会产生误导。

答案 3 :(得分:0)

既不好也不坏。这取决于具体情况。

例如,作为方法链的粉丝,我很少使用其中任何一种。我更喜欢

public Example methodC(Date d) {
  d.setMonth(6);
  return this;
}

虽然在大多数情况下应该避免使用像这样的副作用的方法(我考虑将传入参数的属性更改为副作用,在大多数情况下)。

答案 4 :(得分:0)

我想有一个静默的约定,你没有真正改变Java中的方法参数。有一些例外,比如Collections.sort方法等。在Ruby中,一个很好的习惯是改变参数的方法用感叹号(!)标记。但是,不,Integer和String参数更改不会影响方法范围之外的值。据我所知,他们在整数/字符串池中有对象。

答案 5 :(得分:0)

“我怀疑方法B是大多数人会选择的,但为什么?”

实际上,methodA更新对象month中的字段d1,与方法methodB相同,并且方法methodB返回传递的对象,返回陈述是多余的

这意味着大多数人实际上都使用methodA