推销自己的海盗猫王运营商
因此,Java沒有Elvis運(yùn)算符(或者更正式的名稱是null合并運(yùn)算符或null安全成員選擇)……雖然我個(gè)人不太在意它,但有些人似乎很喜歡它。 當(dāng)一位同事需要幾天后,我坐下來探討了我們的選擇。
而且你知道什么! 您可以很接近方法引用。
總覽
我們首先來看看貓王經(jīng)營者是什么,以及為什么涉及海盜。 然后,我將展示如何使用實(shí)用程序方法來實(shí)現(xiàn)它。
可以在專用的GitHub項(xiàng)目中找到實(shí)現(xiàn),演示和本文中的大多數(shù)示例。 該代碼是Public Domain,因此您可以不受限制地使用它。
他不是死了嗎?
我也這樣認(rèn)為,但顯然不是 。 就像關(guān)于國王還活著的謠言一樣,希望貓王經(jīng)營者的人們也從未消亡。 因此,讓我們看看他們想要什么。
發(fā)布時(shí)間由這哈特福德蓋伊在CC-BY-SA 。
(如果您想自己閱讀有關(guān)它的討論,請(qǐng)參閱OpenJDK郵件列表上的該主題 ,Stephen Colebourne在其中為Java 7提出了這些運(yùn)算符。)
貓王算子
Elvis最簡單的形式是一個(gè)二進(jìn)制運(yùn)算符,它選擇非null操作數(shù),而優(yōu)先選擇左邊的操作數(shù)。 所以代替...
private String getStreetName() {return streetName == null ? "Unknown Street" : streetName; // or like this? // return streetName != null ? streetName : "Unknown Street"; }…你可以寫…
private String getStreetName() {return streetName ?: "Unknown Street"; }我可以用Java來獲得這個(gè)。 對(duì)于經(jīng)常使用的模式,這是一個(gè)不錯(cuò)的捷徑,可以避免我浪費(fèi)時(shí)間來決定哪種方式對(duì)三元運(yùn)算符進(jìn)行排序? :”(因?yàn)槲铱偸窍胫牢沂且殉R?guī)情況放在首位還是要避免雙重否定)。
用靜態(tài)效用函數(shù)來模擬它當(dāng)然是微不足道的,但是,我也說,邊界是毫無意義的。 靜態(tài)導(dǎo)入該方法并使所有代碼閱讀者查找其含義的工作勝過其所提供的小收益。
所以我不是在談?wù)撨@個(gè)貓王。 順便說一句,之所以這樣稱呼,是因?yàn)?#xff1f;:看起來像帶有蓬皮杜鵑的笑臉。 如果不是貓王的話,那會(huì)是誰呢?是的,這就是我們行業(yè)內(nèi)始終選擇名字的方式! 更正式地說,它也稱為空合并運(yùn)算符 。
海盜貓王操作員
然后還有另一件事似乎沒有它自己的名字,這就是我想談的。 它有時(shí)也被稱為貓王,但有時(shí)卻得到方便的名稱,例如“ null-safe成員選擇運(yùn)算符”。 至少,這很好地解釋了它的作用:如果在其上調(diào)用該成員的實(shí)例為null,則短路成員選擇,以便整個(gè)調(diào)用返回null。
當(dāng)您要鏈接方法調(diào)用時(shí),這很方便,但是其中一些可能返回null。 當(dāng)然,您必須對(duì)此進(jìn)行檢查,否則會(huì)遇到NullPointerExeption。 這可能導(dǎo)致相當(dāng)丑陋的代碼。 代替…
private String getStreetName(Order order) {return order.getCustomer().getAddress().getStreetName(); }…你必須寫…
private String getStreetName(Order order) {Customer customer = order == null ? null : order.getCustomer();Address address = customer == null ? null : customer.getAddress();return address.getStreetName(); }這顯然是可怕的。 但是使用“空安全成員選擇運(yùn)算符”:
private String getStreetName(Order order) {return order?.getCustomer()?.getAddress()?.getStreetName(); }看起來更好吧? 是。 它讓您忘記所有那些討厭的空值,對(duì)嗎? 是。 所以這就是為什么我認(rèn)為這是一個(gè)壞主意。
字段經(jīng)常是設(shè)計(jì)錯(cuò)誤的根源。 對(duì)于Java 8,您可以使用Optional來避免null 。 因此,實(shí)際上應(yīng)該沒有什么理由可以使空值拋出變得更加容易。 也就是說,有時(shí)您仍然想要,所以讓我們來看看如何接近。
順便說一下,由于該變體似乎還沒有正式術(shù)語,所以我將其命名為?。 Pirate-Elvis運(yùn)算符(請(qǐng)注意缺少的眼睛)。 記住,您首先在這里閱讀! ;)
實(shí)施海盜貓王運(yùn)營商
現(xiàn)在我們知道了我們?cè)谡f什么,讓我們開始執(zhí)行它。 我們可以為此使用Optional或編寫一些專用方法。
帶可選
只需將第一個(gè)實(shí)例包裝在Optional中,然后將鏈接的函數(shù)應(yīng)用為映射:
private String getStreetName(Order order) {return Optional.ofNullable(order).map(Order::getCustomer).map(Customer::getAddress).map(Address::getStreetName).orElse(null); }這需要很多樣板,但已經(jīng)包含一些關(guān)鍵方面:使用方法引用指定要調(diào)用的方法,并且如果某些內(nèi)容為null(在這種情況下導(dǎo)致空的Optional),則不要調(diào)用這些方法。
我仍然喜歡此解決方案,因?yàn)樗宄赜涗浟诉@些調(diào)用的可選性。 做正確的事情并以O(shè)ptional<String>返回街道名稱也很容易(實(shí)際上使代碼更短)。
使用專用實(shí)用程序方法
從使用Optional的解決方案開始,為這種特殊情況找到更短的方法非常簡單:只需將實(shí)例和方法引用交給專用方法,然后在第一個(gè)值為null時(shí)對(duì)其進(jìn)行分類。
空合并功能應(yīng)用
public static <T1, T2> T2 applyNullCoalescing(T1 target,Function<T1, T2> f) {return target == null ? null : f.apply(target); }public static <T1, T2, T3> T3 applyNullCoalescing(T1 target,Function<T1, T2> f1, Function<T2, T3> f2) {return applyNullCoalescing(applyNullCoalescing(target, f1), f2); }public static <T1, T2, T3, T4> T4 applyNullCoalescing(T1 target,Function<T1, T2> f1, Function<T2, T3> f2,Function<T3, T4> f3) {return applyNullCoalescing(applyNullCoalescing(target, f1, f2), f3); }public static <T1, T2, T3, T4, T5> T5 applyNullCoalescing(T1 target,Function<T1, T2> f1, Function<T2, T3> f2,Function<T3, T4> f3, Function<T4, T5> f4) {return applyNullCoalescing(applyNullCoalescing(target, f1, f2, f3), f4); }(此實(shí)現(xiàn)為簡潔起見進(jìn)行了優(yōu)化。如果顯式實(shí)現(xiàn)每種方法,則可以提高性能。)
使用方法引用可以很容易地調(diào)用這些方法:
private String getStreetName(Order order) {return applyNullCoalescing(order,Order::getCustomer, Customer::getAddress, Address::getStreetName); }還是沒有order?.getCustomer()?.getAddress()?.getStreetName(); 但關(guān)閉。
反射
我們已經(jīng)看到了null合并運(yùn)算符(?:)和null安全成員選擇運(yùn)算符(?。)是什么。 即使后者可能會(huì)鼓勵(lì)不良習(xí)慣(傳遞空值),我們還是使用實(shí)用方法來實(shí)現(xiàn)它,該方法可以通過方法引用來調(diào)用。
您喜歡的任何代碼都可以免費(fèi)使用。
翻譯自: https://www.javacodegeeks.com/2015/03/roll-your-own-pirate-elvis-operator.html
總結(jié)
以上是生活随笔為你收集整理的推销自己的海盗猫王运营商的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 个人辞职原因简短实用(普通员工辞职报告分
- 下一篇: 使用CDI简化JAX-RS缓存