差異處
這裏顯示兩個版本的差異處。
Both sides previous revision 前次修改 下次修改 | 前次修改 | ||
java:effective_java:methods:return_optionals_judiciously [2021/07/05 08:46] tony [Rule#6: Avoid using Optional in fields, method parameters, and collections.] |
java:effective_java:methods:return_optionals_judiciously [2023/06/25 09:48] (目前版本) |
||
---|---|---|---|
行 61: | 行 61: | ||
最後是最有爭議的,是否要將Optional使用於field。反對者主要有以下論述: | 最後是最有爭議的,是否要將Optional使用於field。反對者主要有以下論述: | ||
* Optional不支援序列化,這個是主因。(列為anti-pattern的主因) | * Optional不支援序列化,這個是主因。(列為anti-pattern的主因) | ||
- | * 多消耗4x記憶體空間。(演講中有提及) | + | * 多消耗4倍記憶體空間。(演講中有提及) |
* Optional是一個box,包覆另外一個value物件,這會增加額外的GC開銷。(演講中有提及) | * Optional是一個box,包覆另外一個value物件,這會增加額外的GC開銷。(演講中有提及) | ||
- | 針對以上三點,序列化問題可以透過Guava Optional或Vivr Optional去解決,但也要搭配[[java:jackson:deepclone|Jackson Module]]或Gson的TypeAdapter做對應的處理;多消耗4x記憶體空間在現在時代已經不是嚴重的事情(Stuart Marks的演講有提及);在Java8的情況下,第三點就無法避免了。\\ | + | 針對以上三點,序列化問題可以透過Guava Optional或Vivr Optional去解決,但也要搭配[[java:jackson:deepclone|Jackson Module]]或Gson的TypeAdapter做對應的處理;多消耗4倍記憶體空間在現在時代已經不是嚴重的事情(Stuart Marks的演講有提及);在Java8的情況下,第三點就無法避免了。\\ |
目前已知的是,JDK的[[https://openjdk.java.net/projects/valhalla/|Valhalla]]專案希望能夠將Optional變成Value Type去避免這個問題,也因為有這個計畫,導致目前無法讓Optional去實作Serializable(會產生向下相容問題)。JodaTime作者認為如果這天來臨,內建的Optional應可以用於任何地方:\\ | 目前已知的是,JDK的[[https://openjdk.java.net/projects/valhalla/|Valhalla]]專案希望能夠將Optional變成Value Type去避免這個問題,也因為有這個計畫,導致目前無法讓Optional去實作Serializable(會產生向下相容問題)。JodaTime作者認為如果這天來臨,內建的Optional應可以用於任何地方:\\ | ||
{{:java:effective_java:methods:effectivejava_item55_optional_with_serializable.png|}}\\ | {{:java:effective_java:methods:effectivejava_item55_optional_with_serializable.png|}}\\ | ||
行 78: | 行 78: | ||
\\ | \\ | ||
支持者的論點,主要有兩點: | 支持者的論點,主要有兩點: | ||
- | * 宣告於欄位代表著非必要欄位,語意表達比使用null加註解清楚,更何況大家都不愛寫註解。[[https://nipafx.dev/stephen-colebourne-java-optional-strict-approach/|link]] | + | * 宣告於欄位代表著非必要欄位,語意表達比使用null加註解清楚,更何況大家都不愛寫註解。此外,這個Optional支持者反對null,不偏好JodaTime作者的方法。[[https://nipafx.dev/stephen-colebourne-java-optional-strict-approach/|link]] |
- | * Effective Java Item 55有提及,適用於物件有許多非必要欄位的情況,像是部分更新的UseCaseInput model。如果按照Stuart Marks的建議,使用Null Object Pattern,那將會因此建立許多Sub Classes,非常不方便。 | + | * Effective Java Item 55有提及,適用於物件有許多非必要欄位的情況,像是部分更新的UseCaseInput model。如果按照Stuart Marks的建議使用Null Object Pattern,那將會因此建立許多Sub Classes,非常不方便。 |
* 在使用Lombok的情況下,有人會想將Optional宣告為field;但被Lombok開發人員打槍,因為他愛null。[[https://stackoverflow.com/questions/31670785/optional-in-lombok|link]] | * 在使用Lombok的情況下,有人會想將Optional宣告為field;但被Lombok開發人員打槍,因為他愛null。[[https://stackoverflow.com/questions/31670785/optional-in-lombok|link]] | ||
支持者與反對者比較寫法如下,我認為trade-off就在對於效能、語意、序列化與框架的使用上了,單元測試成本幾乎是一樣的: | 支持者與反對者比較寫法如下,我認為trade-off就在對於效能、語意、序列化與框架的使用上了,單元測試成本幾乎是一樣的: | ||
行 103: | 行 103: | ||
} | } | ||
</code> | </code> | ||
+ | 在Java 8的情況下,我提供以下主要的trade-off比較給大家參考: | ||
+ | * 允許Optional於欄位讓語意清楚: 效能較差、維護成本較高(有序列化需求要特別套其它library)。 | ||
+ | * 允許null於欄位並僅在回傳值使用Optional: 僅有語意問題,null控制好就無大礙。 | ||
==== Rule#7: Avoid using identity-sensitive operations on Optionals. For example don’t use reference equality == with Optionals. ==== | ==== Rule#7: Avoid using identity-sensitive operations on Optionals. For example don’t use reference equality == with Optionals. ==== | ||
這個Rule是告訴大家不要把Optional的物件使用==去操作,要用equals;除了這個以外,也不要把它拿來synchronized。主要原因是Optional本質上是一個包裝物件的box,未來有很大的機會變成Value Type,參考此[[https://openjdk.java.net/projects/valhalla/|link]]。 | 這個Rule是告訴大家不要把Optional的物件使用==去操作,要用equals;除了這個以外,也不要把它拿來synchronized。主要原因是Optional本質上是一個包裝物件的box,未來有很大的機會變成Value Type,參考此[[https://openjdk.java.net/projects/valhalla/|link]]。 |