Boh*_*ian 10 java exception-handling temporal
考虑到通过异常的流控制被(被许多人)视为反模式,是否可以使用时态库(java.time.*)来验证字符串表示有效日期,而不会捕获异常?
请考虑以下代码,它依赖于内部爆炸:
public static boolean isValidDateFormat(String date, DateTimeFormatter formatter) {
try {
formatter.parse(date);
return true;
} catch (DateTimeParseException e) {
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
这可以在不发生解析爆炸的情况下实现吗?有没有类似的东西formatter.isValid(date)(即使内部爆炸 - 这将取决于幕后"JDK impl").
格式引擎java.time.format始终与内部异常一起工作以控制流程。如果您尝试使用ParsePosition. 出现异常,-objectParsePosition甚至不报错:
pp = new ParsePosition(0);
try {
TemporalAccessor t =
DateTimeFormatter.ofPattern("uuuu-MM-dd")
.withResolverStyle(ResolverStyle.STRICT)
.parse("2015-02-29", pp);
} catch (RuntimeException e) {
e.printStackTrace();
System.out.println("Error! " + pp);
// Error! java.text.ParsePosition[index=10,errorIndex=-1]
}
Run Code Online (Sandbox Code Playgroud)
javadoc解释道:
该方法的操作与在 java.text.Format 上使用 ParsePosition 的类似方法略有不同。该类将使用 ParsePosition 上的错误索引返回错误。相比之下,如果发生错误,此方法将抛出 DateTimeParseException,异常包含错误索引。由于此 API 中解析和解析日期/时间的复杂性增加,这种行为更改是必要的。
以下示例尝试使用该方法来避免异常parseUnresolved:
ParsePosition pp = new ParsePosition(0);
try {
TemporalAccessor t =
DateTimeFormatter.ofPattern("uuuu-MM-dd")
.withResolverStyle(ResolverStyle.STRICT)
.parseUnresolved("2015-02-29", pp);
System.out.println("Info! " + t + "/" + pp); // note, no error in pp here!
// Info! {DayOfMonth=29, MonthOfYear=2, Year=2015},null,null/java.text.ParsePosition[index=10,errorIndex=-1]
boolean leapyear = Year.from(t).isLeap();
MonthDay md = MonthDay.from(t);
if (!leapyear && md.getDayOfMonth() == 29 && md.getMonth().getValue() == 2) {
System.out.println("Error!"); // hand-made validation covering a special case
}
} catch (RuntimeException e) {
e.printStackTrace(); // does not happen for given input
}
Run Code Online (Sandbox Code Playgroud)
这毫无例外地有效,但您必须自己编写验证代码,这会带来麻烦。
我一直认为这种抛出异常来控制程序流程的方法是不好的编码实践,因此设计了我自己的 Time4J 库,以尽可能好的方式避免内部异常(不是在所有情况下,但在大多数情况下)例外)。
ParseLog plog = new ParseLog();
PlainDate date = ChronoFormatter.ofDatePattern("uuuu-MM-dd", PatternType.CLDR, Locale.ROOT).parse("2015-02-29", plog);
System.out.println(date); // null
System.out.println(plog.isError() + "/" + plog.getErrorMessage());
// true/Validation failed => DAY_OF_MONTH out of range: 29 [parsed={YEAR=2015, MONTH_AS_NUMBER=2, DAY_OF_MONTH=29}]
Run Code Online (Sandbox Code Playgroud)
这段代码清楚地展示了另一种设计的可能性。java.time如果涉及到大量错误数据的批量处理,我认为所选择的设计是潜在的瓶颈。
| 归档时间: |
|
| 查看次数: |
1876 次 |
| 最近记录: |