<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java!越來越像Kotlin了!!

          共 11096字,需瀏覽 23分鐘

           ·

          2020-08-19 18:35

          作者 |?The Bored Dev

          譯者 | 張衛(wèi)濱

          策劃 | 蔡芳芳

          來自不同編程語言的競爭正促使 Java 不斷吸收新特性,變得更能適應(yīng)時(shí)代和開發(fā)人員的新需求。

          本文最初發(fā)表于 The Bored Dev 網(wǎng)站,由 InfoQ 中文站翻譯分享。

          我們行業(yè)始終有一個(gè)熱門話題,那就是對 Java 的批判,這種批判很大程度上來源于 Java 的繁瑣性以及它所生成的大量樣板式代碼,而這些代碼在很多場景下是根本不需要的。

          雖然我一直以來都很喜歡 Java,但是我不能說這些指責(zé)是錯(cuò)誤的。的確,Java 的繁瑣性以及數(shù)量不菲的雜亂代碼在很多情況下會(huì)很煩人。在大多數(shù)情況下,我們不得不接受我們生活在一個(gè)不完美的世界這一現(xiàn)實(shí),很多時(shí)候,我們必須兩害相權(quán)取其輕。我們都知道,Java 并不完美,但是主要的問題在于在此之前為什么沒有采取任何措施來解決這些問題呢?

          我認(rèn)為,變更需要耗費(fèi)這么長時(shí)間的唯一原因就是 Java 缺乏足夠的競爭。Java 語言之所以能夠主導(dǎo)市場,可能就是因?yàn)槿狈φ嬲母偁帉κ?/strong>,當(dāng)然也要?dú)w功于 Sun 和 Oracle 先后做出的巨大努力。

          Java 提供的強(qiáng)類型安全性,以及作為一個(gè)結(jié)構(gòu)良好的語言所帶來的其他特性,使其成為大型項(xiàng)目中非常流行的語言。通過使用 Java,我們很少會(huì)讓事情變得難以收拾。Java 的另外一個(gè)重要特點(diǎn)是作為多平臺(tái)語言,它運(yùn)行在自己的虛擬機(jī)上,這使其能夠完美契合很多的組織。如果你通過著名的 JIT 編譯器啟用了其自動(dòng)性能優(yōu)化的固有能力,那么在很多情況下都能將糟糕代碼所帶來的影響最小化,這樣我們就有了一組使用 Java 的堅(jiān)實(shí)理由。

          但是,后來發(fā)生了什么呢?接下來的事情就是,能夠像 Java 那樣運(yùn)行在相同 JVM 中的新語言推向了市場,這些語言消除了 Java 中最令人頭疼的問題,并為開發(fā)人員提供了更好的環(huán)境,而且在很多情況下,它們的學(xué)習(xí)曲線非常平坦。

          在繼續(xù)下面的內(nèi)容之前,我們簡要回顧一下 JVM 語言的歷史。


          JVM 語言的歷史

          在開始之前,我想澄清一點(diǎn),那就是我省略掉了一些現(xiàn)有的 JVM 語言,這主要是因?yàn)樗鼈儚膩頉]有具備足夠強(qiáng)的吸引力,不能視為我們行業(yè)中廣泛使用的候選語言。那么,我們就開始快速回顧一下 JVM 語言的歷史。

          圖片出自 Unsplash 站點(diǎn),作者為 Maximilian Weisbecker

          我們的旅程當(dāng)然要從 Java 開始,它是 JVM 領(lǐng)域最古老和最流行的語言。

          Java 語言最初是在 1996 年 1 月份正式發(fā)布的,所以它已經(jīng)有 24 年的歷史了,怎么樣,還不錯(cuò)吧?最初,Java 是一種命令式語言,遵循純粹的面向?qū)ο蟪绦蝻L(fēng)格。它同時(shí)也是強(qiáng)類型語言,Java 的語法在某種程度上與 C++ 和 C 語言很相似,但它被認(rèn)為是一個(gè)改進(jìn)版本,因?yàn)槭褂?Java 編寫代碼要比使用 C 或 C++ 容易得多。另外,在它的批評者中,最大的爭議在于其繁瑣性。

          第二個(gè)發(fā)布的 JVM 語言是 Groovy,它最早出現(xiàn)于 2003 年,不過其第一個(gè)官方和標(biāo)準(zhǔn)版本 1.0 是 2007 年才發(fā)布的。Groovy 的好處在于,它還可以用作腳本語言。Groovy 是一種動(dòng)態(tài)類型語言,所以類型檢查是在運(yùn)行時(shí)進(jìn)行的;這也是一些開發(fā)人員不喜歡 Groovy 的原因之一。我們使用 Groovy 編寫代碼,在編譯時(shí)看起來它是正確的,但是在運(yùn)行時(shí),我們才會(huì)發(fā)現(xiàn)其中有問題。

          圖片來源:維基百科

          接下來出現(xiàn)了另外一種流行的語言,也就是我們要討論的 Scala。Scala 在 2004 年正式發(fā)布,它為 JVM 領(lǐng)域帶來了一種新的編程模型,也就是函數(shù)式編程和它的聲明式方法。我們可以確定,Scala 率先引入了不可變性(immutability)的理念,所以它對 Java 的轉(zhuǎn)變做出了重要貢獻(xiàn)。但另一方面,Scala 的批評者并不喜歡它,因?yàn)樗Z法復(fù)雜,可讀性一般比較差。

          圖片來源:維基百科

          JVM 領(lǐng)域出現(xiàn)的下一個(gè)語言是 Clojure,它是一個(gè)純函數(shù)式語言,最近變得非常流行,但是它最早出現(xiàn)于 2007 年。Clojure 是一種基于 LISP 的語言,其特點(diǎn)是簡單和使用純函數(shù)。在它的缺點(diǎn)中,值得一提的是動(dòng)態(tài)類型(與 Groovy 相同),而且學(xué)習(xí)曲線更陡峭,因?yàn)樗恼Z法與其他 JVM 語言完全不同。如果你對學(xué)習(xí) Clojure 感興趣的話,那么應(yīng)該閱讀如下這兩本好書:“The joy of Clojure”和“Programming Clojure(第三版)”。

          圖片來源:維基百科

          最后但同樣重要的是 Kotlin!Kotlin 在 2016 年 2 月份首次發(fā)布,從那時(shí)開始,它就變得不斷流行起來。該語言是由 JetBrains 公司設(shè)計(jì)的,它有一個(gè)明確的目標(biāo):消除 Java 中所有常見的問題。它的設(shè)計(jì)方式保留了 Java 所有的優(yōu)點(diǎn),但是消除了 Java 的大多數(shù)問題,這也是它為何如此流行的原因,很多人甚至認(rèn)為在未來的幾年中它有可能會(huì)擊敗 Java。如果你想要了解 Kotlin 的更多內(nèi)容的話(我鼓勵(lì)你這樣做,因?yàn)樗且婚T偉大的語言),那么我推薦你閱讀“Kotlin in Action”一書,對于 Java 開發(fā)人員來說,這是一本入門 Kotlin 的優(yōu)秀圖書。

          圖片出自 Unsplash 站點(diǎn),作者為 Louis Tsai

          這就是最重要的 JVM 語言,我們省略了一些不太流行的 JVM 語言,但是我們可以提一下它們的名字:Jython、JRuby、Ceylon、Fantom 等等。你可以通過該地址獲取現(xiàn)有 JVM 語言的全部列表。

          我們可以發(fā)現(xiàn),在最初的八年或十年間,Java 并沒有太多的競爭對手,但從那之后,Java 就面臨一些競爭了,那么有競爭是一件好事兒還是壞事兒呢?


          競爭加劇帶來的好處

          正如我們在前文所述,Java 在早期并沒有太多改變,這很可能是因?yàn)闆]有改變的必要,盡管它遠(yuǎn)遠(yuǎn)稱不上完美,但也已經(jīng)得到了廣泛的使用。

          但是,新的競爭者出現(xiàn)了,這些更現(xiàn)代的語言帶來了新的特性,解決了長期困擾 Java 開發(fā)人員的一些痛點(diǎn)。

          舉例來說,我們看一下 Scala 語言,自 2009 年以來,Scala 變得越來越受歡迎,開發(fā)人員歡迎這種新的函數(shù)式風(fēng)格,它能夠讓他們的編碼更靈活,也能安全輕松地編寫出并行代碼。我們可以在下面的谷歌趨勢圖中看到這個(gè)趨勢:

          圖片來源:theboreddev.com

          那 Oracle 對這種新趨勢的反應(yīng)是什么呢?那就是在 2014 年發(fā)布了 Java Lambdas 和 Streams。很多人都認(rèn)為當(dāng)時(shí)這是 Java 擊敗 Scala 的最大舉措。目前行業(yè)中每個(gè)人都能感受到最近幾年 Scala 因?yàn)槿鄙倭魉馐艿膿p失。

          JVM 領(lǐng)域中存在競爭者的另外一個(gè)好處就是 JIT 編譯器和 JVM 本身正在經(jīng)歷的持續(xù)改進(jìn)。現(xiàn)在,有更多的人對 JVM 優(yōu)化和性能改善感興趣。所以,競爭對每個(gè)人都是好事。

          Kotlin 是這個(gè)領(lǐng)域最新的競爭者。Kotlin 非常重要,因?yàn)樗谝欢ǔ潭壬蠟?Oracle 指明了前進(jìn)方向。Kotlin 表明它能夠保持 Java 好的組成部分,同時(shí)創(chuàng)建一個(gè)更簡潔和快速的編碼語言。

          如果看一下谷歌趨勢的話,我們能夠看到在過去幾年間,Kotlin 的流行程度:

          圖片來源:theboreddev.com

          從圖中可以看出,Kotlin 迅速變得非常流行,但是在最近幾年,它似乎穩(wěn)定了下來。

          Oracle 很好地記錄了業(yè)界對 Kotlin 的反應(yīng),如果你看一下 JDK 15 的發(fā)布說明,就會(huì)發(fā)現(xiàn) Java 的一些新特性基本上就是對 Kotlin 變更的復(fù)制。例如,新的 Java record、文本塊(使用三個(gè)引號(hào)的多行字符串)以及 switch 語句(或多或少借鑒了 Kotlin 的 when 語句)。我們可以通過該地址查閱 JDK 15 的發(fā)布說明。

          剛才提到的這些,我都將其稱為“Java 的 Kotlin 化(Kotlinisation)”。Kotlin 通過成為 Java 有史以來最強(qiáng)的競爭對手,為 Java 指明了發(fā)展的方向。在我看來,Kotlin 是我見過的唯一一種能夠戰(zhàn)勝 Java,并成為行業(yè)領(lǐng)導(dǎo)者的語言。


          Java 的“Kotlin”化

          Java 的一些新特性主要在可讀性方面進(jìn)行了增強(qiáng),并改善了其主要的一個(gè)弱點(diǎn),那就是繁瑣性。我們可以斷言,它與某些 Kotlin 的特性具有相似性

          需要注意,這些特性大多數(shù)都還處于特性預(yù)覽階段,這意味著你安裝 JDK 14 或 JDK 15 時(shí),默認(rèn)不會(huì)啟用這些特性

          Java 特性預(yù)覽指的是一些在發(fā)布版本中包含、但默認(rèn)禁用的特性。在發(fā)行版中包含它們僅僅是為了收集社區(qū)開發(fā)人員的反饋,因此它們更經(jīng)常發(fā)生變更,這也是為何不推薦在生產(chǎn)環(huán)境代碼中使用它們的原因。

          要在編譯時(shí)啟用這些特性,我們需要執(zhí)行如下代碼:

          javac --enable-preview --release 14

          如果你想要在運(yùn)行時(shí)啟用它們的話,如下執(zhí)行如下代碼:

          Javajava?--enable-preview?YourClass

          當(dāng)然,你也可以在 IDE 中啟用它們,但是不要在你的新項(xiàng)目中默認(rèn)啟用預(yù)覽功能。

          我們看一看這些變更,在未來的 Java 版本中,它們會(huì)對我們的編碼產(chǎn)生更大的影響。


          Java record

          Java record 是我們長期以來一直要求的一項(xiàng)特性,我相信你早就多次遇到這樣的場景了,那就是極不情愿地實(shí)現(xiàn) toString、hashCode、equals 方法以及每個(gè)字段的 getter(在這里,我假設(shè)你已經(jīng)不再實(shí)現(xiàn) setter 了,還記得我們在“Java 中新的并發(fā)模型”一文中所討論的不可變性嗎?)。

          Kotlin 提供了數(shù)據(jù)類(data class)來解決這個(gè)問題,Java 也通過發(fā)布 record 類來解決了這個(gè)問題,同樣的問題,Scala 是通過 case 類來解決的。

          這些類的主要目的是在對象中保存不可變的數(shù)據(jù)。讓我們通過一個(gè)示例來看看它在 Java 中能夠帶來多么好的效果。我們實(shí)例化并對比 Employee 類,需要編寫這么多的代碼:

          package com.theboreddev.java14;
          import java.util.Objects;
          public class Employee {private final String firstName;private final String surname;private final int age;private final Address address;private final double salary;
          public Employee(String firstName, String surname, int age, Address address, double salary) {this.firstName = firstName;this.surname = surname;this.age = age;this.address = address;this.salary = salary; }
          public String getFirstName() {return firstName; }
          public String getSurname() {return surname; }
          public int getAge() {return age; }
          public Address getAddress() {return address; }
          public double getSalary() {return salary; }
          @Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false; Employee employee = (Employee) o;return age == employee.age && Double.compare(employee.salary, salary) == 0 && Objects.equals(firstName, employee.firstName) && Objects.equals(surname, employee.surname) && Objects.equals(address, employee.address); }
          @Overridepublic int hashCode() {return Objects.hash(firstName, surname, age, address, salary); }
          @Overridepublic String toString() {return "Employee{" +"firstName='" + firstName + '\'' +", surname='" + surname + '\'' +", age=" + age +", address=" + address +", salary=" + salary +'}'; }}

          它所包含的 Address 對象如下所示:

          package com.theboreddev.java14;
          import java.util.Objects;
          public class Address {private final String firstLine;private final String secondLine;private final String postCode;
          public Address(String firstLine, String secondLine, String postCode) {this.firstLine = firstLine;this.secondLine = secondLine;this.postCode = postCode; }
          public String getFirstLine() {return firstLine; }
          public String getSecondLine() {return secondLine; }
          public String getPostCode() {return postCode; }
          @Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false; Address address = (Address) o;return Objects.equals(firstLine, address.firstLine) && Objects.equals(secondLine, address.secondLine) && Objects.equals(postCode, address.postCode); }
          @Overridepublic int hashCode() {return Objects.hash(firstLine, secondLine, postCode); }
          @Overridepublic String toString() {return "Address{" +"firstLine='" + firstLine + '\'' +", secondLine='" + secondLine + '\'' +", postCode='" + postCode + '\'' +'}'; }}

          為了完成一件簡單的事情,我們寫了太多的代碼,對不對?

          接下來,我們看一下使用新的 Java record 之后,代碼會(huì)是什么樣子:

          public record EmployeeRecord(String firstName, String surname,int age, AddressRecord address, double salary) { }

          再看一下 Address 類:

          public record AddressRecord(String firstLine, StringsecondLine, String postCode) {}

          這和我們前面所編寫的一大堆代碼是同樣的效果,我們不得不承認(rèn):這非常棒!從要保存的代碼數(shù)量和簡潔性方面都是如此。

          現(xiàn)在我們看看新的 switch 語句有什么不同。


          改善 switch 語句

          新的 switch 語句解決了在 Java 中使用 switch 語句的一些固有問題。我們一直以來都被教導(dǎo)應(yīng)該避免使用 switch 語句,因?yàn)樗鼈兒苋菀壮鲥e(cuò)并會(huì)導(dǎo)致代碼重復(fù)。舉例來說,我們很容易遇到某個(gè) case 條件覆蓋不到的場景。

          新的 switch 語句解決了這個(gè)問題,因?yàn)槿绻覀兊?switch 語句沒有涵蓋我們傳遞給它的領(lǐng)域類型的所有范圍,它就無法編譯通過。

          為了闡述該例子,我們使用 Java 創(chuàng)建一個(gè) DayOfTheWeek 枚舉:

          public enum DayOfTheWeek {MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY}

          我們需要 switch 語句告訴我們每周的某一天所對應(yīng)的位置。看一下通過 Java 11 該怎么實(shí)現(xiàn):

          final DayOfTheWeek dayOfTheWeek = DayOfTheWeek.THURSDAY;
          int position = 0;
          switch (dayOfTheWeek) {case MONDAY: position = 1;break;case TUESDAY: position = 2;break;case WEDNESDAY: position = 3;break;case THURSDAY: position = 4;break;case FRIDAY: position = 5;break;case SATURDAY: position = 6;break;case SUNDAY: position = 7;break; }
          System.out.println("Day " + dayOfTheWeek + " is in position " + position + " of the week");

          使用原來的 switch 語句時(shí),我們必須要使用一個(gè)變量,而且如果我們遺漏了一周中的某一天,代碼也能編譯通過。這就是 switch 語句的問題之一,非常容易出錯(cuò)。

          Java 14 會(huì)怎樣改善這種情況呢?我們快速看一下:

          final DayOfTheWeek dayOfTheWeek = DayOfTheWeek.THURSDAY;
          int position = switch (dayOfTheWeek) {case MONDAY -> 1;case TUESDAY -> 2;case WEDNESDAY -> 3;case THURSDAY -> 4;case FRIDAY -> 5;case SATURDAY -> 6;case SUNDAY -> 7; };
          System.out.println("Day " + dayOfTheWeek + " is in position " + position + " of the week");

          我們可以看到,新的 switch 語句可以用作表達(dá)式,而不僅僅是語句。

          這樣帶來的結(jié)果就是更加簡潔,也更具有表述性,這就足以說服我們使用它了。但是,現(xiàn)在的 switch 還有一個(gè)重要改善,那就是如果在 switch 中沒有涵蓋所有 case 的話,它將無法編譯通過。它會(huì)顯示如下錯(cuò)誤:

          Error:(9, 24) java: the switch expression does not cover all possible input values

          現(xiàn)在,我們不會(huì)在 switch 語句中遺漏 case 了,這是一項(xiàng)非常棒的特性。

          這非常類似于 Kotlin 的 when 語句,你可以通過該地址了解該語句的更多信息。

          接下來,我們看一下文本塊。


          文本塊

          你有沒有遇到過將一個(gè)大的 blob JSON 賦值給 Java 變量的場景?你是否也受夠了這種丑陋的代碼?Java 將會(huì)引入多行字符串特性,我們可以通過將它們封裝在三重引號(hào)中來定義它們。當(dāng)這個(gè)功能被正式發(fā)布后,定義多行長字符串會(huì)更加容易。

          我們來看一下兩種模式的差異。假設(shè)我們想要將一個(gè)格式化后的 JSON 存儲(chǔ)到一個(gè)變量中,那么丑陋的代碼如下所示:

          final String text = "{\"widget\": {\n" +" \"debug\": \"on\",\n" +" \"window\": {\n" +" \"title\": \"Sample Konfabulator Widget\",\n" +" \"name\": \"main_window\",\n" +" \"width\": 500,\n" +" \"height\": 500\n" +" },\n" +" \"image\": { \n" +" \"src\": \"Images/Sun.png\",\n" +" \"name\": \"sun1\",\n" +" \"hOffset\": 250,\n" +" \"vOffset\": 250,\n" +" \"alignment\": \"center\"\n" +" },\n" +" \"text\": {\n" +" \"data\": \"Click Here\",\n" +" \"size\": 36,\n" +" \"style\": \"bold\",\n" +" \"name\": \"text1\",\n" +" \"hOffset\": 250,\n" +" \"vOffset\": 100,\n" +" \"alignment\": \"center\",\n" +" \"onMouseUp\": \"sun1.opacity = (sun1.opacity / 100) * 90;\"\n" +" }\n" +"}} ";

          可以更容易地編寫整潔的代碼了:

          final DayOfTheWeek dayOfTheWeek = DayOfTheWeek.THURSDAY;
          int position = 0;
          switch (dayOfTheWeek) { case MONDAY: position = 1; break; case TUESDAY: position = 2; break; case WEDNESDAY: position = 3; break; case THURSDAY: position = 4; break; case FRIDAY: position = 5; break; case SATURDAY: position = 6; break; case SUNDAY: position = 7; break; }
          System.out.println("Day " + dayOfTheWeek + " is in position " + position + " of the week");

          我覺得這樣好太多了。這也是 Kotlin 所支持的,可以在這里的類型定義中找到。

          總之,我們能看到 Java 從它的競爭對手之一,也就是 Kotlin,那里“繼承”了許多方案來解決自己的問題。我們不知道這次 Oracle 在對抗 Kotlin 的崛起方面是否及時(shí)做出了正確的反應(yīng),或許這有點(diǎn)太晚了。但我個(gè)人認(rèn)為 Java 正在朝著正確的方向前進(jìn),盡管這些變化是由它的競爭對手以某種方式觸發(fā)的,而且可能來得有點(diǎn)遲了。

          如前所述,如果這篇文章激發(fā)了你學(xué)習(xí) Kotlin 語言的興趣,我建議你閱讀“Kotlin in Action”,對于 Java 開發(fā)人員來說,這是一門很棒的 Kotlin 入門圖書。


          結(jié) 論

          我認(rèn)為競爭是 Java 語言有史以來所遇到的最好的事情。如果不這樣,Java 就會(huì)作繭自縛。Java 的競爭對手也表明了不同的編程方式是可行的,它表明了前進(jìn)的方向,并讓我們避免使用老式的、陳舊的編寫代碼方式。

          我最近在 Java 中看到了一些變化,以及所有即將發(fā)布的特性和改善,它們正在使 Java 變得比以往任何時(shí)候都更強(qiáng)大。它是一種適應(yīng)當(dāng)前時(shí)代的語言,一種希望發(fā)展并忘記傳統(tǒng)做事方式的語言:Java 的新未來!



          有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)

          歡迎大家關(guān)注Java之道公眾號(hào)


          好文章,我在看??

          瀏覽 35
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中国性爱av | 黄色一级片免费直播 | 亚洲无码小电影 | 又色又爽又黄18 网站 | 国产极品久久久久久久久久 |