2014-03-29 64 views
12

我在玩下面的問題:Using Java 8's Optional with Stream::flatMap,並想添加一個方法到自定義Optional<T>,然後檢查它是否工作。
更準確地說,我想爲我的CustomOptional<T>添加一個stream(),如果沒有值,則返回空流;如果存在,則返回具有單個元素的流。爲什麼選擇<T>宣佈爲最終課堂?

但是,我得出結論,Optional<T>被宣佈爲final。

這是爲什麼?有大量的類沒有被聲明爲final,我個人沒有看到在這裏聲明Optional<T> final的原因。

編輯作爲第二個問題,爲什麼不能所有的方法都是最終的,如果擔心他們會被覆蓋,並且讓類不是最終的?

+0

使用組合物。 – assylias

+1

關於第二個問題:'final'類中的所有方法都是隱式的'final' –

+0

@assylias這不是問題,儘管我會試着去探索它,並提出爲什麼它在這裏沒有幫助。 – skiwi

回答

11

根據this page of the Java SE 8 API docs,Optional<T>是一個基於值的類。根據this page of the API docs,基於價值的類必須是不可變的。

Optional<T>中的所有方法聲明爲final將防止方法被覆蓋,但這不會阻止擴展類添加字段和方法。擴展類和添加一個字段以及更改該字段值的方法會使該子類變化,因此將允許創建可變的Optional<T>。以下是如果Optional<T>不會被聲明爲最終可以創建的這樣一個子類的例子。

//Example created by @assylias 
public class Sub<T> extends Optional<T> { 
    private T t; 

    public void set(T t) { 
     this.t = t; 
    } 
} 

聲明Optional<T>最終防止像上面的一個子類的創建,並因此保證Optional<T>爲始終不變的。

+1

那麼,因爲有人_might_覆蓋類使其變爲可變的規範不會允許子類? 這使我很煩惱的原因是我想用可選流程替換異常流程,使得不是返回一個值或拋出異常,而是隻返回一個可選項並在錯誤中追加異常流,可能需要添加'ifError(Consumer consumer)'和'getCause()'方法。在我看來,這是對傳統繼承的一種很好的運用:擴展 - 但不能使原始行爲無效化。無賴我不能這樣做。 – Groostav

+0

對我來說,就原始狀態而言,它仍然是不變的。 @Groostav所做的情況正是我所遇到的情況,對我來說這似乎是一個非常有效的案例。它遵循由Optional強加的合同,並且對於可選的現有用法是透明的,使得組合或例外不能成爲可用。 – neXus

+0

@neXus,因爲寫了那個評論我已經切換到kotlin(kotlinlang.org)並使用了他們的解決方案之一來解決這個問題。在'Pair's(https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/)和'Either'之間,這是一個解決的問題......對於JVM上的每個人java的。 – Groostav

-1
  1. 根本沒有必要繼承這個類。您可以通過編寫現有方法來完成您想要完成的任務。在你的情況下,它是mapflatMap方法。

  2. 通過聲明一個類final你有效地聲明瞭所有的方法final

0

可能原因與爲什麼String是最終的原因相同;也就是說,這樣Optional類的所有用戶都可以放心,他們收到的實例上的方法總是返回相同的值。

+1

如果所有的方法都是「最終的」,並且這個類本身不是最終的,那麼這仍然是可能的,除非我錯了? – skiwi

+0

不可否認,但是'String'可以說同樣的事情。 Java有一種法西斯主義傾向來保護你免於做錯事。 ;) – Dolda2000

0

正如其他人所說,可選是一個基於值的類,因爲它是一個基於值的類,它應該是不可變的,它需要它是最終的。

但我們錯過了這一點。基於價值的類不可變的主要原因之一是保證線程安全。使其不可變使其線程安全。採取例如字符串或原始包裝像Integer或Float。由於類似的原因,它們被宣佈爲最終。

相關問題