java实现可选形参_Java:可选的可选实现
java實現(xiàn)可選形參
類java.util.Optional被實現(xiàn)為單個不可變的具體類,該類在內(nèi)部處理兩種情況。 一個有元素,一個沒有元素。 讓Optional作為一個接口并讓兩個不同的實現(xiàn)代替實現(xiàn)該接口不是更好的選擇嗎? 畢竟,這就是我們通常被教導(dǎo)要使用的一種面向?qū)ο蟮恼Z言。
在本文中,我們將了解當(dāng)前Optional實現(xiàn)的一些潛在參數(shù)。 我們還將學(xué)習(xí)為什么以不同的方式實現(xiàn)Streams,從而使Streams可以從文件甚至數(shù)據(jù)庫表中獲取。
真正的可選實現(xiàn)
真正的java.util.Optional::get實現(xiàn)如下所示:
public T get() { if (value == null ) { throw new NoSuchElementException( "No value present" ); } return value; }可以看出,有兩個代碼路徑。 一種是值是null(沒有元素,并且不會引發(fā)異常),另一種是值是其他值(返回值)。
可選可選實現(xiàn)
讓我們假裝我們將回到時光機中,并被要求再次實現(xiàn)Optional 。 我認為我們中的許多人可能會提出一個初始解決方案,就像下面的解決方案(我將其命名為假設(shè)接口Option以便我們可以將其與“實際”接口進行區(qū)分)具有兩個不同的實現(xiàn)(此處為EmptyOption和PresentOption ):
public interface Option<T> { T get(); boolean isPresent(); public <U> Option<U> map(Function<? super T, ? extends U> mapper); static <T> Option<T> empty() { return (Option<T>) EmptyOption.EMPTY; } (Option<T>) EmptyOption.EMPTY; } <T> Option<T> of(T value) { static <T> Option<T> of(T value) { return new PresentOption<>(value); } PresentOption<>(value); } <T> Option<T> ofNullable(T value) { static <T> Option<T> ofNullable(T value) { return value == null ? empty() : of(value); ? empty() : of(value); } } final class EmptyOption<T> implements Option<T> { static final EmptyOption<?> EMPTY = new EmptyOption<>(); private EmptyOption() {} @Override public T get() { throw new NoSuchElementException(); } NoSuchElementException(); } @Override public boolean isPresent() { return false ; } ; } @Override public <U> Option<U> map(Function<? super T, ? extends U> mapper) { requireNonNull(mapper); return (Option<U>) EMPTY; } } final class PresentOption<T> implements Option<T> { private final T value; PresentOption(T value) { this .value = requireNonNull(value); } .value = requireNonNull(value); } @Override public T get() { return value; } value; } @Override public boolean isPresent() { return true ; } ; } @Override public <U> Option<U> map(Function<? super T, ? extends U> mapper) { requireNonNull(mapper); return Option.ofNullable(mapper.apply(value)); } }為了簡潔起見,僅示出了幾種方法,但是原理保持不變:針對存在元素和不存在元素的情況的不同實現(xiàn)。 這給出了更清晰的代碼,也使任何人都可以實現(xiàn)可選選項。
分析
我有信心在構(gòu)思Optional時,JDK團隊已對這種解決方案進行了評估,并且我認為不選擇該解決方案是明智的決定。 Optional主要目的是“包裝”返回值,以防止NPE和返回原始空值的其他缺點。 我還認為設(shè)計目標(biāo)是使用Optional對性能的影響應(yīng)該很小甚至可以忽略不計。
在下文中,我推測了一些論點,以選擇以上所創(chuàng)造的當(dāng)前的Optional實現(xiàn)。
剖面污染
JIT編譯器按需編譯Java字節(jié)碼,以提高解釋字節(jié)碼的性能。
為了有效地做到這一點,JIT編譯器能夠收集每種已知方法的統(tǒng)計信息。 每個方法都可以具有一個MethodData對象,該對象包含有關(guān)如何使用該方法的度量標(biāo)準(zhǔn),并且一旦JVM認為該方法足夠“溫暖”(即在某種意義上已被充分調(diào)用),便會創(chuàng)建該對象。
創(chuàng)建和維護MethodData過程稱為“分析”。
當(dāng)調(diào)用之間使用的方法大不相同時,就會發(fā)生“配置文件污染”,包括但不限于提供交替的非null / null元素并調(diào)用不同的多態(tài)方法(例如,參數(shù)是類型T泛型,并且被調(diào)用的方法調(diào)用T::equals )。 Java的基本功能是其動態(tài)調(diào)用方法的能力。 因此,當(dāng)調(diào)用Option::get時, EmptyOption::get或
最終調(diào)用PresentOption::get取決于調(diào)用時存在的實現(xiàn)。
一旦該方法被調(diào)用了10,000次,JIT編譯器就會使用MethodData創(chuàng)建一個有效的已編譯代碼段,根據(jù)迄今為止收集的統(tǒng)計信息,該代碼段將以最佳方式執(zhí)行。
因此,如果元素始終存在(使用PresentOption ),并且牢記這一點編譯代碼,但隨后突然出現(xiàn)EmptyOption ,則代碼必須“退出”并采用慢得多的代碼路徑。
僅在最后一個類中使用Optional ,就不可能再有Optional方法的任何其他實現(xiàn),因此,不會因不同的實現(xiàn)而造成配置文件污染。 JIT可以確定性地并合理地快速編譯代碼。
但是,等等,JVM不可能在啟動時檢查所有類并確定實際上只有兩個實現(xiàn)類。
Option ,然后它可以解決整個問題? 好吧,不。 我們可以隨時隨意添加類,因此無法安全地枚舉特定接口的所有可能實現(xiàn)。 至少要等到我們有了Java中真正的密封類時,才能進行。
原料藥污染
如果人們可以自由編寫Optional自定義實現(xiàn),那么與內(nèi)置Optional相比,這些實現(xiàn)很可能會遭受設(shè)計缺陷/偏差。 同樣,人們可能會讓他們自己的類型實現(xiàn)Optional接口,這增加了JIT編譯器/分析器的負擔(dān),因此將誘使人們使用非預(yù)期的復(fù)合類型(例如Foo implements Bar, Optional<Bazz>) 。
另外, Optional現(xiàn)在是Java不可或缺的一部分,因此,可以使它與JDK本身一起有效發(fā)展,包括內(nèi)聯(lián)類和其他即將推出的Java新功能。
可選與流
與Optional相反, java.util.stream.Stream和專用版本(例如IntStream )確實是接口。 為什么Stream不像Optional那樣具體地進行最后的上課?
好吧,Streams有一套完全不同的要求。 可以從Collection或數(shù)組中獲取Stream但是有很多更強大的獲取Stream 。 可以從文件,套接字,隨機生成器甚至從數(shù)據(jù)庫表中獲取Stream 。 如果Stream被密封,將無法實現(xiàn)這些功能。
Speedment Stream是一個庫的示例,該庫允許從幾乎任何數(shù)據(jù)庫中獲取標(biāo)準(zhǔn)Java流。 在此處閱讀有關(guān)Speedment Stream的更多信息。
結(jié)論
Optional密封,有充分的理由。 Optional的內(nèi)部實現(xiàn)不太清楚,但這是值得付出的代價,它具有更好的性能和更清晰的用戶代碼。
流是非密封接口,任何人都可以實現(xiàn),并且可用于從各種來源(包括文件和數(shù)據(jù)庫表)獲取元素。 Speedment Stream ORM可用于從數(shù)據(jù)庫表獲取Streams。
在此處下載Speedment Stream。
翻譯自: https://www.javacodegeeks.com/2019/08/java-optional-implementation-optional.html
java實現(xiàn)可選形參
總結(jié)
以上是生活随笔為你收集整理的java实现可选形参_Java:可选的可选实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手机、平板远控电脑的黄金搭档,向日葵智能
- 下一篇: 精打细算油盐_Java:Chronicl