Webアプリでのフォーム入力に限らす、Javaでは変数への入力実行の後の妥当性チェックを記述していると
どうしてもコードが長くなる。
コードが長いと、タイプミスの確率も上がるし、なにしろ読むのが辛い。長くても何回も if文を書きたくない。
java.util.Optional を単純に使うので連結を考えてみる。入力規則外を例外捕捉で処理する考え方。。。
例)日付の入力、"/" 区切りの日付文字列
String datestring = "2017/09/31"; try{ LocalDate dt = Optional.ofNullable(datestring) .filter(e->Pattern.compile("^\\d{4}/(0[1-9]|1[012])/(0[1-9]|[12][0-9]|3[01])$").matcher(e).matches()) .filter(e->{ DateFormat format = new SimpleDateFormat("yyyy/MM/dd"); format.setLenient(false); try{ format.parse(e); return true; }catch(ParseException ex){ throw new RuntimeException(ex); } }) .map(e->LocalDate.parse(e, DateTimeFormatter.ofPattern("yyyy/MM/dd"))) .orElseThrow(()->new IllegalArgumentException("Format Error")); // 正常時の処理 }catch(Exception ex){ if(ex instanceof IllegalArgumentException){ // 書式エラー、null の場合を捕捉 } if (ex.getCause() instanceof ParseException){ // 存在できない日付の場合を捕捉 } ex.printStackTrace(); }
古いJava の java.text.DateFormat 、 java.text.SimpleDateFormat を使って
ありえない日付のチェックをしている。ここをスマートに書きたいのだがどうにもならない。
上のコードは、null も、nullでない書式エラーも、IllegalArgumentException で捕捉する。
setLenient を実行した format で parse して発生する ParseException ラムダで飛び越えられないので
RuntimeExceptionでラップする。
せめて、ありえない日付のチェックを外にメソッドにする。
public static boolean checkDate(String strDate, String pattern){ DateFormat format = new SimpleDateFormat(pattern); format.setLenient(false); try{ format.parse(strDate); return true; }catch(ParseException e){ return false; } }
書き直す。
String datestring = "2017/09/31"; try{ LocalDate dt = Optional.ofNullable(datestring) .filter(e->Pattern.compile("^\\d{4}/(0[1-9]|1[012])/(0[1-9]|[12][0-9]|3[01])$").matcher(e).matches()) .filter(e->checkDate(e, "yyyy/MM/dd")) .map(e->LocalDate.parse(e, DateTimeFormatter.ofPattern("yyyy/MM/dd"))) .orElseThrow(()->new IllegalArgumentException("Format Error")); // 正常時の処理 }catch(Exception ex){ if(ex instanceof IllegalArgumentException){ // 書式エラー、null の場合を捕捉 } if (ex.getCause() instanceof ParseException){ // 存在できない日付の場合を捕捉 } ex.printStackTrace(); }
少しは綺麗になる。