"exploit" java 按值调用是否明智

Is it wise to "exploit" java call-by-value

考虑以下情况。用户可以输入类似 30D, 90D, 180D, 360D, 1M, 3M, 6M, 12M, 1Y (D=日,M=月,Y=年)。

我想用以下两种方法计算月数。

    private int getLengthOfPeriodInMonths(Integer lengthOfPeriod, String unitOfPeriod) {
        int periodInMonths = lengthOfPeriod;
        if ("D".equals(unitOfPeriod)) {
            periodInMonths = lengthOfPeriod / 30;
        } else if ("Y".equals(unitOfPeriod)) {
            periodInMonths = lengthOfPeriod * 12;
        }
        return periodInMonths;
    }

    private int getLengthOfPeriodInMonths(Integer lengthOfPeriod, String unitOfPeriod) {
        if ("D".equals(unitOfPeriod)) {
            lengthOfPeriod = lengthOfPeriod / 30;
        } else if ("Y".equals(unitOfPeriod)) {
            lengthOfPeriod = lengthOfPeriod * 12;
        }
        return lengthOfPeriod;
    }

因为 java 使用按值调用,引用作为值传递 lengthOfPeriod 不会在方法之外更改。不知道用什么比较合适

我知道这个方法可以通过使用枚举 Periods 或类似的东西来重构。不过我们先不讨论这个。

唯一的区别是您在第一种方法中使用了自己的变量int periodInMonths = lengthOfPeriod;。但这不是必需的!

你可以使用第二个..它做了它应该做的!

int lengthOfPeriodInMonths = getLengthOfPeriodInMonths(lengthOfPeriod, unitOfPeriod);

并且您在 lengthOfPeriodInMonths

中存储了方法之外的计算整数

P.S.: 这个调用

lengthOfPeriod = lengthOfPeriod / 30;

等同于

lengthOfPeriod = new Integer(lengthOfPeriod / 30);

(在Java中查找"auto-boxing")。

所以,正如您所说,Java 使用呼叫间隔值。变量 lengthOfPeriod 在此调用中被分配了一个新的引用。所以这个计算会在方法之外丢失!这就是为什么您必须 return 新计算的值!

分配给方法参数不是一个好主意(恕我直言,它们应该默认为 final)。如果你真的想避免额外的变量(并不是说它真的有所作为),你可以在你的 if 子句中加入 returns。

但不要像"automatic local variables"那样使用参数。它会导致很难发现错误,并且不会使您的代码更高效。

第一个建议:永远不要修改方法参数。它们应该始终反映方法的用户传递的值。

第二个建议:如果有人建议您永远不要做某事,尤其是当他或她使用短语 "never ever" 时,请对他或她的建议持保留态度。没有没有例外的规则(从来没有;-)。这些规则是很好的经验法则,但请始终使用您自己的判断。选择您认为更清晰的解决方案。我知道在某些情况下,我发现修改方法参数比替代方法更具可读性。

例如,有时您可能希望允许该方法的用户将 null 传递给该方法,然后用一些默认值替换它。我找到以下方法

public void doSomething(String s) {
    if (s == null) s = "";
    System.out.println(s);
}

比为了包含默认值而引入局部变量要清楚得多:

public void doSomething(final String s) {
    String sOrEmpty = s == null ? "" : s;
    System.out.println(sOrEmpty);
}