别在函数里改写参数
参数是调用方与被调方之间的契约:在函数体内改写参数值,会让「输入到底是什么」这件事消失,阅读与调试都要在脑内重放一遍赋值过程。移除对参数的赋值,就是改用局部变量承接中间结果,让参数在整个函数里保持只读。
基本信息
| 为什么 | 参数被改写后原始输入不可见,跟踪困难 |
|---|---|
| 做法 | 局部变量承接中间值,参数视为只读 |
| 语言差异 | 值传递语言影响小,引用语义语言容易牵连调用方对象 |
| 风格指南 | 多数团队把禁止改写入参写成硬性检查项 |
典型使用场景
- 累加与换算:用局部结果承接,而不是在入参上直接做加减
- 默认值处理:用局部变量取默认值,保留「未传参」这一信息
- 循环复用:局部变量做游标,函数语义更明确
- 代码评审:把入参只读作为可执行的评审检查项
- 静态检查:把禁止参数重赋值固化成规则,交给工具守住
Java 示例
Java 示例
// 之前:入参被就地修改,原始输入丢失
double discount(double inputVal) {
if (inputVal > 100) inputVal -= 10; // 原始值无法再观察
return inputVal;
}
// 之后:局部变量承接,参数保持只读
double discount(double inputVal) {
double result = inputVal; // 中间结果独立存放
if (result > 100) result -= 10;
return result;
}常见改写对照
| 场景 | 不推荐 | 推荐 |
|---|---|---|
| 累加 | 直接对参数做加减 | 局部变量承接后再返回 |
| 默认值 | 给参数重新赋默认值 | 局部变量赋值后再使用 |
| 对象字段 | 改参数指向对象的字段 | 返回新对象或使用局部变量 |
| 循环游标 | 用参数当索引变量 | 声明局部游标变量 |
值传递不等于安全:改写入参这个变量本身不影响调用方,但改写入参指向对象的字段会影响调用方。字符串、数组、集合、映射在多数语言里都是引用语义,这类副作用最隐蔽,评审要单独看对象字段赋值。
可变默认参数是同类问题的变体:用可变对象做默认值会被多次调用共享并累积,应改用表示缺失的占位值,在函数内部新建容器。