最近在公司做项目时,有一个小功能点就是身份证号码校验,即判断是否是合理的身份证号码。不想重复造轮子,想着公司的一些基础组件可能有这个功能,一找还真有,原作者代码逻辑应该是正确的,但是风格有点呵呵了,各种嵌套if … else…,也不是说这样就不好,但是有更好的流程控制写法。那就是卫语句,这种写法我也是看了阿里巴巴java开发手册才知道,也推荐大家去看看。
那么什么是卫语句呢?先想一个业务场景,很多时候真正的业务代码可能在嵌套多次才执行,其他分支只是简单报错返回的情况。如果嵌套过多,当你读到最里面一层的时候,估计你已经记不起来前面的条件判断逻辑了,为了简化这种情况,可以把特殊情况隔离到立即结束执行的单独条件中,也可以叫做“失败前置”,只要有一个条件不通过,就快速返回失败,如果到了最后一行,说明前面所有判断都通过,剩下的就是执行你真正的业务代码。在重构法则上,这种就叫Guard Clause法则,就是卫语句。这种程序结构优点就是可以把我们的视线从多层嵌套的层层判断处理中解放出来,集中精力处理真正的业务代码,且能够使得代码结构清晰可读,方便后续维护。
下面是身份证号码校验代码原版本及我改写的卫语句版本,大家可以对比看下。
// 身份证号码校验——原始版本
public static boolean checkIdentifyNumber(String identifyNumber) {
if (StringUtils.isBlank(identifyNumber)) {
return false;
} else {
identifyNumber = identifyNumber.toLowerCase();
String[] ValCodeArr = new String[]{"1", "0", "x", "9", "8", "7", "6", "5", "4", "3", "2"};
String[] Wi = new String[]{"7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2"};
String Ai = "";
if (identifyNumber != null && (identifyNumber.length() == 18 || identifyNumber.length() == 15)) {
if (identifyNumber.length() == 18) {
Ai = identifyNumber.substring(0, 17);
} else if (identifyNumber.length() == 15) {
Ai = identifyNumber.substring(0, 6) + "19" + identifyNumber.substring(6, 15);
}
if (!isNumeric(Ai)) {
// 身份证18位号码除最后一位外,都应为数字
return false;
} else {
String strYear = Ai.substring(6, 10);
String strMonth = Ai.substring(10, 12);
String strDay = Ai.substring(12, 14);
if (!isDataFormat(strYear + "-" + strMonth + "-" + strDay)) {
// 身份证生日无效
return false;
} else {
GregorianCalendar gc = new GregorianCalendar();
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
try {
if (gc.get(1) - Integer.parseInt(strYear) > 150 || gc.getTime().getTime() - s.parse(strYear + "-" + strMonth + "-" + strDay).getTime() < 0L) {
// 身份证生日不在有效范围
return false;
}
} catch (Exception var14) {
var14.printStackTrace();
return false;
}
if (Integer.parseInt(strMonth) <= 12 && Integer.parseInt(strMonth) != 0) {
if (Integer.parseInt(strDay) <= 31 && Integer.parseInt(strDay) != 0) {
Map<String, String> h = getAreaCode();
if (h.get(Ai.substring(0, 2)) == null) {
// 身份证地区编码错误
return false;
} else {
int TotalmulAiWi = 0;
int modValue;
for(modValue = 0; modValue < 17; ++modValue) {
TotalmulAiWi += Integer.parseInt(String.valueOf(Ai.charAt(modValue))) * Integer.parseInt(Wi[modValue]);
}
modValue = TotalmulAiWi % 11;
String strVerifyCode = ValCodeArr[modValue];
Ai = Ai + strVerifyCode;
if (identifyNumber.length() == 18 && !Ai.equalsIgnoreCase(identifyNumber)) {
// 身份证无效,不是合法的身份证号码
return false;
} else {
return true;
}
}
} else {
// 身份证日期无效
return false;
}
} else {
// 身份证月份无效
return false;
}
}
}
} else {
// 身份证长度错误
return false;
}
}
}
// 身份证号码校验——卫语句版本
public static boolean checkIdentifyNumber(String identifyNumber) {
if (StringUtils.isBlank(identifyNumber)) {
return false;
}
identifyNumber = identifyNumber.toLowerCase();
String[] ValCodeArr = new String[]{"1", "0", "x", "9", "8", "7", "6", "5", "4", "3", "2"};
String[] Wi = new String[]{"7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2"};
String Ai = "";
if (identifyNumber.length() != 18 && identifyNumber.length() != 15) {
// 身份证长度错误
return false;
}
if (identifyNumber.length() == 18) {
Ai = identifyNumber.substring(0, 17);
}
if (identifyNumber.length() == 15) {
Ai = identifyNumber.substring(0, 6) + "19" + identifyNumber.substring(6, 15);
}
if (!isNumeric(Ai)) {
// 身份证18位号码除最后一位外,都应为数字
return false;
}
String strYear = Ai.substring(6, 10);
String strMonth = Ai.substring(10, 12);
String strDay = Ai.substring(12, 14);
if (!isDataFormat(strYear + "-" + strMonth + "-" + strDay)) {
// 身份证生日无效
return false;
}
GregorianCalendar gc = new GregorianCalendar();
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
try {
if (gc.get(Calendar.YEAR) - Integer.parseInt(strYear) > 150 || gc.getTime().getTime() - s.parse(strYear + "-" + strMonth + "-" + strDay).getTime() < 0L) {
// 身份证生日不在有效范围
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
if (Integer.parseInt(strMonth) > 12 || Integer.parseInt(strMonth) <= 0) {
// 身份证月份无效
return false;
}
if (Integer.parseInt(strDay) > 31 && Integer.parseInt(strDay) <= 0) {
// 身份证日期无效
return false;
}
Map<String, String> h = getAreaCode();
if (h.get(Ai.substring(0, 2)) == null) {
// 身份证地区编码错误
return false;
}
int TotalmulAiWi = 0;
int modValue;
for(modValue = 0; modValue < 17; ++modValue) {
TotalmulAiWi += Integer.parseInt(String.valueOf(Ai.charAt(modValue))) * Integer.parseInt(Wi[modValue]);
}
modValue = TotalmulAiWi % 11;
String strVerifyCode = ValCodeArr[modValue];
Ai = Ai + strVerifyCode;
if (identifyNumber.length() == 18 && !Ai.equalsIgnoreCase(identifyNumber)) {
// 身份证无效,不是合法的身份证号码
return false;
}
return true;
}