如何防止Setter方法中的参数被非法修改?附Weather类代码示例
你这个问题问到点子上了——本质上是要通过Setter方法牢牢把控类内部状态的合法性,避免外部传入的参数破坏我们预设的业务规则(比如你设定的温度范围限制)。先看看你写的Weather类代码:
public class Weather { private int temperature; //Set temperature to t. //If t goes below -15, temperature should become -15. //If t goes above 40, temperature should become 40. //If t is already between -15 and 40, it should not be changed. public void setTemperature(int t){ if(t>= -15 && t<= 40){ temperature = t; } else if(t< -15){ temperature = -15; } else if(t> 40){ temperature = 40; } } }
你当前的代码其实已经做了基础的参数校验,但可以从几个维度优化,进一步强化对参数修改的控制,彻底杜绝不当修改的可能:
1. 简化校验逻辑,提升可读性与健壮性
你现在的分支判断是正确的,但可以用Math工具类简化写法,让规则更清晰,也减少分支逻辑出错的概率:
public void setTemperature(int t) { // 直接把传入的t钳制在[-15, 40]的合法范围内 this.temperature = Math.max(-15, Math.min(t, 40)); }
一行代码就搞定了所有边界处理,逻辑一目了然,也不会因为分支遗漏导致规则失效。
2. 严格封装内部状态,杜绝直接访问
确保temperature字段始终是private的,绝对不要对外暴露该字段的引用(如果是引用类型的话更要注意,比如自定义对象,要避免返回原引用)。如果需要对外提供温度值,返回值副本——不过这里是基本类型,直接返回就没问题,因为基本类型是值传递,外部拿到的是拷贝,不会影响内部状态。
3. 添加防御性校验,主动提醒错误调用
如果你想在调用者传入明显不合理的值时(比如温度是-100或者200,明显是业务错误),主动抛出异常提醒,而不是默默修正,可以加一层异常判断:
public void setTemperature(int t) { // 设置一个宽泛的"异常阈值",超出则认为调用者传错了 if (t < -50 || t > 100) { throw new IllegalArgumentException("温度值" + t + "超出合理范围,请传入-15到40之间的数值"); } // 正常进行范围钳制 this.temperature = Math.max(-15, Math.min(t, 40)); }
这样能提前发现调用端的错误,避免调用者误以为自己传入的非法值已经生效。
4. 改用不可变类(业务允许的话)
如果你的Weather类不需要频繁修改状态,完全可以设计成不可变类——去掉Setter方法,在构造对象时就完成参数校验,之后状态不再允许修改:
public final class Weather { private final int temperature; public Weather(int t) { // 构造时就完成范围校验 this.temperature = Math.max(-15, Math.min(t, 40)); } public int getTemperature() { return temperature; } }
这种方式从根本上杜绝了外部修改内部状态的可能,安全性最高,也符合不可变对象的设计原则。
总的来说,核心思路就是在参数进入类内部之前就完成严格的校验与修正,再通过封装、防御性编程甚至不可变设计,确保类的内部状态始终符合业务规则,不会被外部不当修改。
内容的提问来源于stack exchange,提问作者lettuce

