成都网站制作成都网站制作,经营网站 备案,旅游网站开发项目介绍,建设私人网站我不时地想念Java中SQL的三值BOOLEAN语义。 在SQL中#xff0c;我们有#xff1a; TRUE FALSE UNKNOWN #xff08;也称为NULL #xff09; 时不时地#xff0c;我希望自己也能用Java表达这种UNKNOWN或UNINITIALISED语义#xff0c;而普通的true和false还不够。 实现… 我不时地想念Java中SQL的三值BOOLEAN语义。 在SQL中我们有 TRUE FALSE UNKNOWN 也称为NULL 时不时地我希望自己也能用Java表达这种UNKNOWN或UNINITIALISED语义而普通的true和false还不够。 实现一个ResultSetIterator 例如当为jOOλ实现ResultSetIterator时一个为Java 8建模SQL流的简单库 SQL.stream(stmt, Unchecked.function(r -new SQLGoodies.Schema(r.getString(FIELD_1),r.getBoolean(FIELD_2))
))
.forEach(System.out::println); 为了实现Java 8 Stream 我们需要构造一个Iterator 然后可以将其传递给新的Spliterators.spliteratorUnknownSize方法 StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false
); 在Stack Overflow上可以看到另一个示例 。 在实现Iterator接口时我们必须实现hasNext()和next() 。 请注意在Java 8中 remove现在具有默认实现因此我们不再需要实现它。 虽然在大多数情况下对next()的调用之前仅是对hasNext()的调用但是Iterator协定中对此没有要求。 完全可以这样写 if (it.hasNext()) {// Some stuff// Double-check again to be sureif (it.hasNext() it.hasNext()) {// Yes, were paranoidif (it.hasNext())it.next();}
} 如何将Iterator调用转换为JDBC ResultSet上的支持调用 我们需要调用ResultSet.next() 。 我们可以进行以下翻译 Iterator.hasNext() !ResultSet.isLast() Iterator.next() ResultSet.next() 但是那个翻译是 昂贵 没有正确处理空的ResultSet 并非在所有JDBC驱动程序中都实现对于结果集类型为TYPE_FORWARD_ONLY的ResultSet对isLast方法的支持是可选的 因此我们必须在内部维护一个标志该标志告诉我们 如果我们已经调用了ResultSet.next() 那个电话的结果是什么 除了创建第二个变量之外为什么不使用三值的java.lang.Boolean 。 这是jOOλ的可能实现 class ResultSetIteratorT implements IteratorT {final Supplier? extends ResultSet supplier;final FunctionResultSet, T rowFunction;final Consumer? super SQLException translator;/*** Whether the underlying {link ResultSet} has* a next row. This boolean has three states:* ul* linull: its not known whether there * is a next row/li* litrue: there is a next row, and it* has been pre-fetched/li* lifalse: there arent any next rows/li* /ul*/Boolean hasNext;ResultSet rs;ResultSetIterator(Supplier? extends ResultSet supplier, FunctionResultSet, T rowFunction, Consumer? super SQLException translator) {this.supplier supplier;this.rowFunction rowFunction;this.translator translator;}private ResultSet rs() {return (rs null) ? (rs supplier.get()) : rs;}Overridepublic boolean hasNext() {try {if (hasNext null) {hasNext rs().next();}return hasNext;}catch (SQLException e) {translator.accept(e);throw new IllegalStateException(e);}}Overridepublic T next() {try {if (hasNext null) {rs().next();}return rowFunction.apply(rs());}catch (SQLException e) {translator.accept(e);throw new IllegalStateException(e);}finally {hasNext null;}}
} 如您所见 hasNext()方法仅在其之前为null时才本地缓存hasNext三值布尔状态。 这意味着多次调用hasNext() 直到调用next() 这将重置hasNext缓存状态。 如果需要 hasNext()和next()前进ResultSet游标。 可读性 你们中有些人可能会认为这不利于可读性。 他们将引入一个新变量例如 boolean hasNext;
boolean hasHasNextBeenCalled; 麻烦的是您仍在实现三值布尔状态但分配给两个变量很难以一种比实际java.lang.Boolean解决方案更易读的方式来命名它们。 此外两个boolean变量实际上有四个状态值因此发生错误的风险会略有增加。 每个规则都有其例外。 自从引入Option / Optional以来一直存在的null -is-bad历史准则将null用于上述语义是一个很好的例外。 换句话说哪种方法最好 没有TRUE或FALSE答案只有UNKNOWN 小心一点 但是正如我们在上一篇博客文章中所讨论的那样 如果可能的话应该避免从API方法返回null 。 在这种情况下显式使用null作为建模状态的一种方法很好因为此模型封装在我们的ResultSetIterator 。 但是请避免将此类状态泄漏到API外部。 翻译自: https://www.javacodegeeks.com/2014/05/three-state-booleans-in-java.html