java中布尔值做比较_Java中的三态布尔值
java中布爾值做比較
我不時地錯過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, we're 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 ResultSetIterator<T> implements Iterator<T> {final Supplier<? extends ResultSet> supplier;final Function<ResultSet, T> rowFunction;final Consumer<? super SQLException> translator;/*** Whether the underlying {@link ResultSet} has* a next row. This boolean has three states:* <ul>* <li>null: it's not known whether there * is a next row</li>* <li>true: there is a next row, and it* has been pre-fetched</li>* <li>false: there aren't any next rows</li>* </ul>*/Boolean hasNext;ResultSet rs;ResultSetIterator(Supplier<? extends ResultSet> supplier, Function<ResultSet, 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
java中布爾值做比較
總結
以上是生活随笔為你收集整理的java中布尔值做比较_Java中的三态布尔值的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中的8种原始类型
- 下一篇: 在Eclipse中使用Java 12