参数有效性检测的隐患
在平时开发中,相信大家都见过大量的这样的代码:
void doXXX(String s){if(s == null){return;}//do something...
}
或者是另一种形式:
void doXXX(String s){if(s != null){//do something...}
}
但是这种程序看上去是在为安全考虑,但是却包含了一些隐患。文本就分享一些我对这类隐患的一些思考。(本文以判空为示例,这种想法可以延伸到其他参数有效的判断上)
问题描述
上面两个示例中的过程定义都不包含返回值,过程的执行是为了副作用(side-effect),但是过程的定义使得调用存在两种情况:1. 参数合法,产生期望的副作用;2. 参数不合法,调用无效。
但是在调用方看来:
doXXX(str);
doYYY();
不管是那种情况,doXXX
调用都会正常执行完,然后执行doYYY
。也就是说调用方不知道这个doXXX
调用是否产生了预期的副作用,如果这里doYYY
的调用或者后续程序执行依赖doXXX
的副作用,那么就会导致问题。
究其根源,还是在于过程内容和名称(或者说期望)不符导致:这里的doXXX
表示这个过程干xxx事,但是过程的内容并不一定干这个事情。
优化方案
对于上述问题,有以下处理方法
方法一:修改过程名
因为过程的内容是尝试/可能干这个xxx事,所以可以改为:
void mayDoXXX(String s){if(s == null){return;}//do something...
}
或
void tryDoXXX(String s){if(s == null){return;}//do something...
}
方法二:添加返回值
因为外部不知道这个过程是否正常调用,所以可以加返回值来表示正常调用与否:
boolean doSomething(String s){if(s == null){return false;}//do something...
}
这样调用方就可以通过检查返回值来判断调用是否生效。
方法三:非法情况抛出异常
boolean
返回值只能表示正常与否,如果像告诉调用方无法正常执行内容的原因,还是得靠异常机制:
void doSomething(String s){if(s == null){throw new IllegalArgumentException("s can not be null!");}//do something...
}