"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);
}
考虑以下情况。用户可以输入类似 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);
}