Java A的新本地变量类型推断
對(duì)于編程語(yǔ)言迷來(lái)說(shuō),新聞幾乎比這更令人興奮!
現(xiàn)在有一個(gè)狀態(tài)為“候選”的本地變量類型推斷的JEP 286 。 以及Brian Goetz的反饋請(qǐng)求,我很想邀請(qǐng)您參加: http : //mail.openjdk.java.net/pipermail/platform-jep-discuss/2016-March/000037.html
請(qǐng)這樣做,調(diào)查僅在3月9日至3月16日開放!
這不是將要實(shí)現(xiàn)的功能。 這可能實(shí)現(xiàn)。 因此,尚無(wú)特定的Java版本,這就是為什么我將Java版本命名為“ A”(對(duì)于Awesome)。
什么是局部變量類型推斷,為什么好呢?
讓我們看一下其他各種語(yǔ)言已經(jīng)存在了一段時(shí)間的功能。 在此博客文章中,我想討論總體思想,而不是討論可能針對(duì)Java計(jì)劃的特定實(shí)現(xiàn),因?yàn)檫@還為時(shí)過(guò)早,而且我當(dāng)然不了解如何將其適合Java。 。
在Java和其他某些語(yǔ)言中,類型總是明確和冗長(zhǎng)地聲明。 例如,您編寫如下內(nèi)容:
// Java 5 and 6 List<String> list = new ArrayList<String>();// Java 7 List<String> list = new ArrayList<>();請(qǐng)注意,在Java 7中,如何通過(guò)有用的菱形運(yùn)算符<>添加了一些語(yǔ)法糖。 它有助于以Java方式消除不必要的冗余,即通過(guò)應(yīng)用“目標(biāo)類型”,這意味著類型是由“目標(biāo)”定義的。 可能的目標(biāo)是:
- 局部變量聲明
- 方法參數(shù)(從方法的外部和內(nèi)部)
- 班級(jí)成員
由于在許多情況下, 必須明確聲明目標(biāo)類型(方法參數(shù),類成員),因此Java的方法很有意義。 但是,對(duì)于局部變量,實(shí)際上不需要聲明目標(biāo)類型。 由于類型定義綁定在一個(gè)非常局部的范圍內(nèi),因此無(wú)法逃脫,因此編譯器很可能會(huì)在沒有源代碼明確的情況下從“源類型”推斷出它。 這意味著,我們將能夠執(zhí)行以下操作:
// Java A as suggested in the JEP// infers ArrayList<String> var list = new ArrayList<String>();// infers Stream<String> val stream = list.stream();在上面的示例中, var表示可變(非最終)局部變量,而val表示不可變(最終)局部變量。 請(qǐng)注意,從來(lái)沒有真正需要過(guò)列表類型,就像我們編寫以下內(nèi)容一樣,今天已經(jīng)推斷出了類型:
stream = new ArrayList<String>().stream();這與lambda表達(dá)式?jīng)]有什么不同,在Java 8中我們已經(jīng)有了這種類型推斷:
List<String> list = new ArrayList<>();// infers String list.forEach(s -> {System.out.println(s); };將lambda參數(shù)視為局部變量。 這種lambda表達(dá)式的另一種語(yǔ)法可能是:
List<String> list = new ArrayList<>();// infers String list.forEach((val s) -> {System.out.println(s); };其他語(yǔ)言都有這個(gè),但是好嗎?
這些其他語(yǔ)言包括:C#,Scala和JavaScript(如果需要的話)。 YAGNI可能是對(duì)此功能的常見反應(yīng)。 對(duì)于大多數(shù)人來(lái)說(shuō),不能一直輸入所有類型只是為了方便。 某些人在閱讀代碼時(shí)可能更喜歡看到明確記錄下來(lái)的類型。 特別是,當(dāng)您具有復(fù)雜的Java 8 Stream處理管道時(shí),很難跟蹤沿途推斷的所有類型。 在我們有關(guān)jOOλ的窗口函數(shù)支持的文章中可以看到一個(gè)示例:
BigDecimal currentBalance = new BigDecimal("19985.81");Seq.of(tuple(9997, "2014-03-18", new BigDecimal("99.17")),tuple(9981, "2014-03-16", new BigDecimal("71.44")),tuple(9979, "2014-03-16", new BigDecimal("-94.60")),tuple(9977, "2014-03-16", new BigDecimal("-6.96")),tuple(9971, "2014-03-15", new BigDecimal("-65.95"))) .window(Comparator.comparing((Tuple3<Integer, String, BigDecimal> t) -> t.v1, reverseOrder()).thenComparing(t -> t.v2), Long.MIN_VALUE, -1) .map(w -> w.value().concat(currentBalance.subtract(w.sum(t -> t.v3).orElse(BigDecimal.ZERO)) ));上面實(shí)現(xiàn)了運(yùn)行總計(jì)計(jì)算,得出:
+------+------------+--------+----------+ | v0 | v1 | v2 | v3 | +------+------------+--------+----------+ | 9997 | 2014-03-18 | 99.17 | 19985.81 | | 9981 | 2014-03-16 | 71.44 | 19886.64 | | 9979 | 2014-03-16 | -94.60 | 19815.20 | | 9977 | 2014-03-16 | -6.96 | 19909.80 | | 9971 | 2014-03-15 | -65.95 | 19916.76 | +------+------------+--------+----------+盡管由于現(xiàn)有Java 8的有限類型推斷功能而需要聲明Tuple3類型( 另請(qǐng)參見有關(guān)廣義目標(biāo)類型推斷的本文 ),但是您是否可以跟蹤所有其他類型? 您可以輕松預(yù)測(cè)結(jié)果嗎? 有些人喜歡短款,有些則聲稱:
@lukaseder我總是在Scala中聲明我的類型。 我真的認(rèn)為除了語(yǔ)法糖之外,這沒有給Java的游戲增加任何東西。
— Steve Chaloner(@steve_objectify) 2016年3月10日
另一方面,您是否想手動(dòng)寫下類似Tuple3<Integer, String, BigDecimal> ? 或者,在使用jOOQ時(shí) ,您更喜歡以下哪個(gè)版本的相同代碼?
// Explicit typing // ---------------------------------------- for (Record3<String, Integer, Date> record : ctx.select(BOOK.TITLE, BOOK.ID, BOOK.MODIFIED_AT).from(BOOK).where(TITLE.like("A%")) ) {// Do things with recordString title = record.value1(); }// "Don't care" typing // ---------------------------------------- for (Record record : ctx.select(BOOK.TITLE, BOOK.ID, BOOK.MODIFIED_AT).from(BOOK).where(TITLE.like("A%")) ) {// Do things with recordString title = record.getValue(0, String.class); }// Implicit typing // ---------------------------------------- for (val record : ctx.select(BOOK.TITLE, BOOK.ID, BOOK.MODIFIED_AT).from(BOOK).where(TITLE.like("A%")) ) {// Do things with recordString title = record.value1(); }我敢肯定,很少有人真的愿意顯式地寫下整個(gè)泛型類型,但是如果您的編譯器仍然可以記住這一點(diǎn),那真是太棒了,不是嗎? 這是一個(gè)可選功能。 您始終可以恢復(fù)為顯式類型聲明。
使用地點(diǎn)差異的邊緣案例
沒有這種類型推斷,有些事情是不可能的,它們與使用站點(diǎn)的差異以及Java中實(shí)現(xiàn)的泛型的細(xì)節(jié)有關(guān)。 使用使用場(chǎng)所差異和通配符,可以構(gòu)造無(wú)法分配給任何東西的“危險(xiǎn)”類型,因?yàn)樗鼈兪遣淮_定的。 有關(guān)詳細(xì)信息,請(qǐng)閱讀Ross Tate關(guān)于在Java的Type System中馴服通配符的論文 。
當(dāng)從方法返回類型暴露時(shí),使用站點(diǎn)差異也是一個(gè)痛苦,如在某些庫(kù)中可以看到的:
- 不在乎他們給用戶帶來(lái)的痛苦
- 沒有找到更好的解決方案,因?yàn)镴ava沒有聲明站點(diǎn)差異
- 忽略了這個(gè)問(wèn)題
一個(gè)例子:
interface Node {void add(List<? extends Node> children);List<? extends Node> children(); }想象一下一個(gè)樹數(shù)據(jù)結(jié)構(gòu)庫(kù),其中樹節(jié)點(diǎn)返回其子級(jí)列表。 從技術(shù)上講正確的子類型為L(zhǎng)ist<? extends Node> List<? extends Node>因?yàn)樽蛹?jí)是Node子類型,并且使用Node子類型列表是完全可以的。
從API設(shè)計(jì)的角度來(lái)看,在add()方法中接受此類型非常有用。 例如,它允許人們添加List<LeafNode> 。 但是,從children()返回它是可怕的,因?yàn)楝F(xiàn)在唯一的選擇是:
// Raw type. meh List children = parent.children();// Wild card. meh List<?> children = parent.children();// Full type declaration. Yuk List<? extends Node> children = parent.children();使用JEP 286,我們也許可以解決所有這些問(wèn)題,并擁有第四個(gè)不錯(cuò)的選擇:
// Awesome. The compiler knows it's // List<? extends Node> val children = parent.children();結(jié)論
局部變量類型推斷是一個(gè)熱門話題。 它是完全可選的,我們不需要它。 但這使很多事情變得容易得多,尤其是在使用大量仿制藥時(shí)。 我們已經(jīng)看到,在使用lambda表達(dá)式和復(fù)雜的Java 8 Stream轉(zhuǎn)換時(shí),類型推斷是一項(xiàng)致命功能。 當(dāng)然,要在一條較長(zhǎng)的語(yǔ)句中跟蹤所有類型會(huì)比較困難,但是同時(shí),如果拼出了這些類型,則會(huì)使該語(yǔ)句非常難以閱讀(并且通常也很難編寫)。
類型推斷有助于使開發(fā)人員提高工作效率,而又不放棄類型安全性。 實(shí)際上,這鼓勵(lì)了類型安全,因?yàn)锳PI設(shè)計(jì)人員現(xiàn)在不那么愿意向用戶公開復(fù)雜的泛型類型,因?yàn)橛脩艨梢愿p松地使用這些類型( 請(qǐng)參見jOOQ示例 )。
實(shí)際上,此功能已經(jīng)在各種情況下在Java中提供,只是在為局部變量賦值并為其命名時(shí)不存在。
無(wú)論您的意見是什么:請(qǐng)確保將其分享給社區(qū)并回答此調(diào)查: http : //mail.openjdk.java.net/pipermail/platform-jep-discuss/2016-March/000037.html
期待Java A,A代表Awesome。
翻譯自: https://www.javacodegeeks.com/2016/03/java-new-local-variable-type-inference.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的Java A的新本地变量类型推断的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 电脑内存条价格(16g内存条多少钱一个)
- 下一篇: 使用Java 8进行分组,转换和归约