Java 8 Friday:可选将保留为Java中的一个选项
在Data Geekery ,我們喜歡Java。 而且,由于我們真的很喜歡jOOQ的流暢的API和查詢DSL ,我們對Java 8將為我們的生態系統帶來什么感到非常興奮。
Java 8星期五
每個星期五,我們都會向您展示一些不錯的教程風格的Java 8新功能,這些功能利用了lambda表達式,擴展方法和其他好東西。 您可以在GitHub上找到源代碼 。
可選:Java中的新選項
到目前為止,Java 8的所有新增功能讓我們非常激動。總而言之,這是一場革命,比以往任何時候都重要。 但是也有一兩個瘡點。 其中之一就是Java將永遠不會真正擺脫
空:十億美元的錯誤
在以前的博客文章中,我們已經解釋了使用Ceylon語言處理NULL的優點, Ceylon語言找到了解決此問題的最佳解決方案之一-至少在注定永遠支持空指針的JVM上。 在Ceylon中,可空性是一個標志,可以通過在類型名稱后附加問號來將其添加到每種類型。 一個例子:
void hello() {String? name = process.arguments.first;String greeting;if (exists name) {greeting = "Hello, ``name``!";}else {greeting = "Hello, World!";}print(greeting); }真漂亮 結合流敏感的類型 ,您將永遠不會再遇到可怕的NullPointerException :
最近在手術室里。 極客和戳
其他語言也引入了Option類型。
最突出的是:Scala 。
Java 8現在還引入了Optional類型(以及OptionalInt , OptionalLong , OptionalDouble類型-稍后將進一步介紹這些類型)
Optional如何運作?
Optional背后的要點是包裝一個Object并提供便利的API以流暢地處理可空性。 這與Java 8 lambda表達式配合得很好,該表達式允許延遲執行操作。 一個例子:
Optional<String> stringOrNot = Optional.of("123");// This String reference will never be null String alwaysAString =stringOrNot.orElse("");// This Integer reference will be wrapped again Optional<Integer> integerOrNot = stringOrNot.map(Integer::parseInt);// This int reference will never be null int alwaysAnInt = stringOrNot.map(s -> Integer.parseInt(s)).orElse(0);流暢的API,尤其是在新的Java 8 Streams API中具有上述優點,它廣泛使用Optional 。 例如:
Arrays.asList(1, 2, 3).stream().findAny().ifPresent(System.out::println);上面的代碼將把Stream中的任何數字打印到控制臺上,但前提是存在這樣的數字。
未對舊API進行改造
出于明顯的向后兼容的原因,“舊API”未進行改裝。 換句話說,與Scala不同,Java 8不在JDK上使用Optional 。 實際上,在Streams API中唯一使用Optional地方。 如您在Javadoc中所見,用法非常稀缺:
http://docs.oracle.com/javase/8/docs/api/java/util/class-use/Optional.html
這使Optional難以使用。 之前我們已經寫過關于該主題的博客 。 具體而言,API中不存在Optional類型不能保證不可為空。 如果將Streams轉換為collections并且將collections轉換為streams,這尤其令人討厭。
Java 8 Optional類型是危險的
參數多態性
Optional對它的“受感染” API的最壞影響是參數多態性,或者簡稱為:泛型。 當您對類型進行推理時,您將很快理解:
// This is a reference to a simple type: Number s;// This is a reference to a collection of // the above simple type: Collection<Number> c;泛型通常用于通常被認為是合成的內容。 我們有一個Collection 的 String 。 使用Optional ,會稍微濫用這種組合語義(在Scala和Java中都是如此)來“包裝”可能為空的值。 現在,我們有:
// This is a reference to a nullable simple type: Optional<Number> s;// This is a reference to a collection of // possibly nullable simple types Collection<Optional<Number>> c;到目前為止,一切都很好。 我們可以替換類型以獲得以下內容:
// This is a reference to a simple type: T s;// This is a reference to a collection of // the above simple type: Collection<T> c;但現在輸入通配符和使用地點差異。 我們可以寫
// No variance can be applied to simple types: T s;// Variance can be applied to collections of // simple types: Collection<? extends T> source; Collection<? super T> target;在Optional的上下文中,以上類型是什么意思? 直觀地講,我們希望這與Optional<? extends Number> Optional<? extends Number>或Optional<? super Number> Optional<? super Number> 。 在上面的示例中,我們可以編寫:
// Read a T-value from the source T s = source.iterator().next();// ... and put it into the target target.add(s);但這對Optional不再起作用
Collection<Optional<? extends T>> source; Collection<Optional<? super T>> target;// Read a value from the source Optional<? extends T> s = source.iterator().next();// ... cannot put it into the target target.add(s); // Nope…而且,當我們擁有Optional和更復雜的API時,沒有其他方法可以推斷出使用地點的差異。
如果將通用類型擦除添加到討論中,情況會變得更糟。 我們不再刪除上述Collection的組件類型,而實際上也刪除了任何引用的類型。 從運行時/反射的角度來看,這幾乎就像在各處使用Object一樣!
即使對于簡單的用例,泛型系統也非常復雜。 Optional只會使事情變得更糟。 很難將Optional與傳統的集合API或其他API融合在一起。 與Ceylon的流敏感鍵入甚至Groovy的elvis運算符的易用性相比, Optional就像您的大錘。
將其應用于API時要小心!
原始類型
為什么Optional仍然是一個非常有用的添加的主要原因之一是,由于我們還具有OptionalInt , OptionalLong , OptionalDouble類型,因此“對象流”和“原始流”具有“統一的API”。
換句話說,如果您正在使用原始類型,則可以以幾乎相同的方式切換流的構造并重用其余的流API使用源代碼。 比較這兩個鏈:
// Stream and Optional Optional<Integer> anyInteger = Arrays.asList(1, 2, 3).stream().filter(i -> i % 2 == 0).findAny(); anyInteger.ifPresent(System.out::println);// IntStream and OptionalInt OptionalInt anyInt = Arrays.stream(new int[] {1, 2, 3}).filter(i -> i % 2 == 0).findAny(); anyInt.ifPresent(System.out::println);換句話說,鑒于在JDK API中很少使用這些新類型,因此這種類型在一般情況下的可疑用途(如果改型為非常向后兼容的環境)以及泛型擦除對Optional的影響,我們敢說
真正添加此類型的唯一原因是為引用和原始類型提供更統一的Streams API
太難了 令我們感到疑惑的是,我們是否最終應該完全擺脫原始類型。
哦還有
… Optional不是可Serializable 。
不。 不可Serializable 。 例如,與ArrayList不同。 通常的原因:
在JDK可序列化中進行處理會使我們的維護成本急劇增加,因為這意味著該表示將一直凍結。 這限制了我們將來開發實現的能力,而我們無法輕松修復錯誤或提供增強功能的情況數量非常之多,而這種情況本來就很簡單。 因此,盡管對您來說,這看起來像是一個“可序列化的實現”的簡單問題,但不僅限于此。 解決早期的選擇以使某些東西可序列化所消耗的工作量是驚人的。
引用Brian Goetz,來自: http : //mail.openjdk.java.net/pipermail/jdk8-dev/2013-September/003276.html
想討論Optional嗎? 在reddit上閱讀以下主題:
- / r / java
- / r /編程
請繼續關注本博客系列中發布的更多令人興奮的Java 8內容。
翻譯自: https://www.javacodegeeks.com/2014/04/java-8-friday-optional-will-remain-an-option-in-java.html
總結
以上是生活随笔為你收集整理的Java 8 Friday:可选将保留为Java中的一个选项的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 玩使命召唤9元以内4400i3单游戏配置
- 下一篇: 塔吊备案登记证图片(塔吊备案登记证)