真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java中Groovy、Scala和Clojure的共同點(diǎn)是什么

Java中Groovy、Scala和Clojure的共同點(diǎn)是什么,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

創(chuàng)新互聯(lián)憑借在網(wǎng)站建設(shè)、網(wǎng)站推廣領(lǐng)域領(lǐng)先的技術(shù)能力和多年的行業(yè)經(jīng)驗(yàn),為客戶提供超值的營(yíng)銷型網(wǎng)站建設(shè)服務(wù),我們始終認(rèn)為:好的營(yíng)銷型網(wǎng)站就是好的業(yè)務(wù)員。我們已成功為企業(yè)單位、個(gè)人等客戶提供了網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站制作服務(wù),以良好的商業(yè)信譽(yù),完善的服務(wù)及深厚的技術(shù)力量處于同行領(lǐng)先地位。

Java 編程語(yǔ)言誕生時(shí)所面臨的限制與如今的開(kāi)發(fā)人員所面臨的條件有所不同。具體來(lái)講,由于上世紀(jì) 90  年代中期的硬件的性能和內(nèi)存限制,Java 語(yǔ)言中存在原語(yǔ)類型。從那時(shí)起,Java  語(yǔ)言不斷在演化,通過(guò)自動(dòng)裝箱(autobox)消除了許多麻煩操作,而下一代語(yǔ)言(Groovy、Scala 和  Clojure)更進(jìn)一步,消除了每種語(yǔ)言中的不一致性和沖突。

在這一期的文章中,我將展示下一代語(yǔ)言如何消除一些常見(jiàn)的 Java 限制,無(wú)論是語(yǔ)法上還是默認(rèn)行為上。***個(gè)限制是原語(yǔ)數(shù)據(jù)類型的存在。

原語(yǔ)的消亡

Java 語(yǔ)言最開(kāi)始有 8 對(duì)原語(yǔ)和相應(yīng)的類型包裝器類(最初用于解決性能和內(nèi)存限制),并通過(guò)自動(dòng)裝箱逐步地淡化了它們之間的區(qū)別。Java 下一代語(yǔ)言更進(jìn)一步,讓開(kāi)發(fā)人員覺(jué)得好像根本不存在差別。

Groovy 完全隱藏了原語(yǔ)類型。例如,int 始終表示 Integer,Groovy 自動(dòng)處理數(shù)字類型的上變換,防止出現(xiàn)數(shù)值溢出錯(cuò)誤。例如,請(qǐng)查看清單 1 中的 Groovy shell 交互:

清單 1. Groovy 對(duì)原語(yǔ)的自動(dòng)處理

groovy:000> 1.class ===> class java.lang.Integer groovy:000> 1e12.class ===> class java.math.BigDecimal

在清單 1 中,Groovy shell 顯示,即使是常量也是通過(guò)底層的類來(lái)表示的。因?yàn)樗袛?shù)字(和其他偽裝的原語(yǔ))都是真正的類,所以可以使用元編程技術(shù)。這些技術(shù)包括將方法添加到數(shù)字中(這通常用于構(gòu)建特定領(lǐng)域的語(yǔ)言,即 DSL),支持 3.cm 這樣的表達(dá)式。在后面介紹可擴(kuò)展性的那期文章中,我會(huì)更全面地介紹此功能。

與 Groovy 中一樣,Clojure 自動(dòng)屏蔽原語(yǔ)與包裝器之間的區(qū)別,允許對(duì)所有類型執(zhí)行方法調(diào)用,自動(dòng)處理容量的類型轉(zhuǎn)換。Clojure 封裝了大量底層優(yōu)化,這已在語(yǔ)言文檔中詳細(xì)說(shuō)明(參閱 參考資料)。在許多情況下,可提供類型 hints,使編譯器能夠生成更快的代碼。例如,無(wú)需使用 (defn sum[x] ... ) 定義方法,可以添加一個(gè)類型提示,比如 (defn sum[^float x] ... ),它會(huì)為臨界區(qū) (critical section) 生成更高效的代碼。

Scala 也屏蔽了原語(yǔ)之間的區(qū)別,通常對(duì)代碼的時(shí)效性部件使用底層原語(yǔ)。它還允許在常量上調(diào)用方法,就像 2.toString 中一樣。借助其混搭原語(yǔ)和包裝器的能力,比如 Integer,Scala 比 Java 自動(dòng)裝箱更加透明。例如,Scala 中的 == 運(yùn)算符可在原語(yǔ)和對(duì)象引用上正確運(yùn)行(比較值,而不是引用),而不同于相同運(yùn)算符的 Java 版本。Scala 還包含一個(gè) eq 方法(以及一個(gè)對(duì)稱的 ne 方法),它始終比較底層引用類型是否等效?;径?,Scala 會(huì)智能地切換默認(rèn)行為。在 Java 語(yǔ)言中,== 會(huì)對(duì)引用數(shù)據(jù)進(jìn)行比較,您幾乎不需要這么做,可以使用不太直觀的 equals() 比較值。在 Scala 中,== 能正確運(yùn)行(比較值),無(wú)論底層實(shí)現(xiàn)是什么,它還提供了一個(gè)方法來(lái)執(zhí)行不太常見(jiàn)的引用相等性檢查 (reference equality check)。

Scala 的這一特性表明,Java 下一代語(yǔ)言的一個(gè)重要優(yōu)勢(shì)在于:將低級(jí)細(xì)節(jié)卸載到語(yǔ)言和運(yùn)行時(shí),開(kāi)發(fā)人員能夠有更多的時(shí)間考慮更高級(jí)的問(wèn)題。

簡(jiǎn)化默認(rèn)行為

人們的看法高度一致,大部分 Java 開(kāi)發(fā)人員都認(rèn)為,在 Java 語(yǔ)言中常見(jiàn)的操作需要太多的語(yǔ)法。例如,屬性定義和其他樣板代碼使類定義變得很雜亂,掩蓋了重要的方法。所有 Java 下一代語(yǔ)言都提供了簡(jiǎn)化創(chuàng)建和訪問(wèn)過(guò)程的途徑。

Scala 中的類和 case 類

Scala 已簡(jiǎn)化了類定義,可為您自動(dòng)創(chuàng)建存取函數(shù)、賦值函數(shù)和構(gòu)造函數(shù)。例如,請(qǐng)查看清單 2 中的 Java 類:

清單 2. Java 中簡(jiǎn)單的 Person

class Person {     private String name;     private int age;      Person(String name, int age) {         this.name = name;         this.age = age;     }      public String getName() {         return name;     }      public int getAge() {         return age;     }      public void setAge(int age) {         this.age = age;     }      @Override     public String toString() {         return name + " is " + age + " years old.";     } }

清單 2 中惟一的非樣板代碼是改寫的 toString() 方法。構(gòu)造函數(shù)和所有方法都由 IDE 生成。相比快速生成代碼,在以后輕松理解它更為重要。無(wú)用的語(yǔ)法增加了您在理解底層含義之前必須使用的代碼量。

Scala Person 類

令人震驚的是,清單 3 中用 Scala 編寫的簡(jiǎn)單 3 行定義就創(chuàng)建了一個(gè)等效的類:

清單 3. Scala 中的等效類

class Person(val name: String, var age: Int) {   override def toString = name + " is " + age + " years old." }

清單 3 中的 Person 類濃縮成了一個(gè)可變的 age 屬性、一個(gè)不可變的 name 屬性,以及一個(gè)包含兩個(gè)參數(shù)的構(gòu)造函數(shù),還有我改寫的 toString() 方法。很容易看到這個(gè)類的獨(dú)特之處,因?yàn)橛腥さ牟糠譀](méi)有埋藏在語(yǔ)法中。

Scala 的設(shè)計(jì)強(qiáng)調(diào)了以最少的語(yǔ)法創(chuàng)建代碼的能力,它使許多語(yǔ)法成為可選語(yǔ)法。清單 4 中的簡(jiǎn)單類演示了一個(gè)將字符串更改為大寫字母的 Verbose 類:

清單 4. Verbose 類

class UpperVerbose {   def upper(strings: String*) : Seq[String] = {     strings.map((s:String) => s.toUpperCase())   } }

清單 4 中的許多代碼都是可選的。清單 5 給出了相同的代碼,現(xiàn)在使用了一個(gè) object 而不是 class

清單 5. 一個(gè)轉(zhuǎn)換為大寫的更簡(jiǎn)單的對(duì)象

object Up {   def upper(strings: String*) = strings.map(_.toUpperCase()) }

對(duì)于等效于 Java 靜態(tài)方法的 Scala 代碼,可創(chuàng)建一個(gè) object(與獨(dú)體實(shí)例等效的 Scala 內(nèi)置實(shí)體)而不是一個(gè)類。方法的返回類型、用于將單行方法主體分開(kāi)的括號(hào),以及 清單 4 中無(wú)用的 s 參數(shù)都從清單 5 中消失了。Scala 中的這種 “可折疊語(yǔ)法” 有利有弊。使用可折疊語(yǔ)法,能夠以非常符合語(yǔ)言習(xí)慣的方式編寫代碼,但這讓不熟悉的人難以理解您的代碼。

case 類

用作數(shù)據(jù)持有者的簡(jiǎn)單類在面向?qū)ο蟮南到y(tǒng)中很常見(jiàn),尤其是必須與不同系統(tǒng)通信的系統(tǒng)。這種類型的類的流行使得 Scala 項(xiàng)目向前推進(jìn)了一步,創(chuàng)造了 case 類。case 類自動(dòng)提供了多種便捷的語(yǔ)法:

  • 可根據(jù)該類的名稱創(chuàng)建一個(gè)工廠方法。例如,可以在不使用 new 關(guān)鍵字的情況下構(gòu)造一個(gè)新實(shí)例:val bob = Person("Bob", 42)。

  • 該類的參數(shù)列表中的所有參數(shù)都自動(dòng) val,也就是說(shuō),它們是作為不可變的內(nèi)部字段來(lái)維護(hù)的。

  • 編譯器為您的類生成合理的默認(rèn) equals()、hashCode()toString() 方法。

  • 編譯器將一個(gè) copy() 方法添加到類中,以便您可返回某個(gè)副本來(lái)執(zhí)行變體式更改。

Java 下一代語(yǔ)言不僅修復(fù)了語(yǔ)法瑕疵,還促進(jìn)了對(duì)現(xiàn)代軟件工作原理的更準(zhǔn)確的理解,朝這個(gè)方向塑造它們的工具。

Groovy 的自動(dòng)生成屬性

在 Java 下一代語(yǔ)言中,Groovy 與 Java 語(yǔ)法最接近,為常見(jiàn)情形提供了稱為 “語(yǔ)法糖 (syntactic-sugar)” 的代碼生成方法。參見(jiàn)清單 6 中簡(jiǎn)單的 Groovy Person 類:

清單 6. Groovy Person

class Person {   private name   def age    def getName() {     name   }    @Override   String toString() {     "${name} is ${age} years old."   } }  def bob = new Person(name: "Bob", age:42)  println(bob.name)

在 清單 6 的 Groovy 代碼中,定義一個(gè)字段 def 會(huì)得到一個(gè)存取函數(shù)和賦值函數(shù)。如果僅喜歡其中一個(gè)函數(shù),可自行定義它,就像我對(duì) name 屬性所做的那樣。盡管該方法名為 getName(),但我仍然可以通過(guò)更直觀的 bob.name 語(yǔ)法訪問(wèn)它。

如果希望 Groovy 自動(dòng)為您生成 equals()hashCode() 方法對(duì),可以向類中添加 @EqualsAndHashCode 注釋。該注釋使用 Groovy 的抽象語(yǔ)法樹(shù) (Abstract Syntax Tree, AST) 轉(zhuǎn)換 生成基于您的屬性的方法(參閱 參考資料)。在默認(rèn)情況下,此注釋僅考慮屬性(而不考慮字段);如果添加了 includeFields=true 修飾符,它也會(huì)考慮字段。

Clojure 的映射式記錄

可在 Clojure 中像其他語(yǔ)言中一樣創(chuàng)建相同 Person 類,但這并不符合語(yǔ)言習(xí)慣。傳統(tǒng)上,Clojure 等語(yǔ)言依靠映射(名稱-值對(duì))數(shù)據(jù)結(jié)構(gòu)來(lái)持有這種類型的信息,并使用了一些處理該結(jié)構(gòu)的函數(shù)。盡管仍然可以在映射中建模結(jié)構(gòu)化的數(shù)據(jù),但目前更常見(jiàn)的情形是使用記錄。記錄是 Clojure 對(duì)具有屬性(常常是嵌套的)的類型名的更加正式的封裝,每個(gè)實(shí)例具有相同的語(yǔ)義含義。(Clojure 中的記錄就像類 C 語(yǔ)言中的 struct。)

例如,請(qǐng)考慮以下人員定義:

(def mario {:fname "Mario"             :age "18"})

鑒于此結(jié)構(gòu),可以通過(guò) (get mario :age) 訪問(wèn) age。簡(jiǎn)單的訪問(wèn)是映射上的一個(gè)常見(jiàn)操作。借助 Clojure,可以利用使用鍵充當(dāng)著映射上的存取函數(shù) 的語(yǔ)法糖,以便使用更有效的 (:age mario) 速記法。Clojure 期望對(duì)映射進(jìn)行操作,所以它提供了大量語(yǔ)法糖來(lái)簡(jiǎn)化此操作。

Clojure 還擁有訪問(wèn)嵌套的映射元素的語(yǔ)法糖,如清單 7 所示:

清單 7. Clojure 的速記式訪問(wèn)

(def hal {:fname "hal"           :age "17"           :address {:street "Enfield Tennis Academy"                     :city "Boston"                     :state "MA"}})  (println (:fname hal)) (println (:city (:address hal))) (println (-> hal :address :city))

在 清單 7 中,我定義了一個(gè)名為 hal 的嵌套數(shù)據(jù)結(jié)構(gòu)。對(duì)外部元素的訪問(wèn)按預(yù)期進(jìn)行 ((:fname hal))。如 清單 7 中倒數(shù)第二行所示,Lisp 語(yǔ)法執(zhí)行 “內(nèi)外” 評(píng)估。首先,必須從 hal 獲取 address 記錄,然后訪問(wèn) city 字段。因?yàn)?“內(nèi)外” 評(píng)估是一種常見(jiàn)用法,所以 Clojure 提供了一個(gè)特殊運(yùn)算符(-> thread 運(yùn)算符)來(lái)反轉(zhuǎn)表達(dá)式,使它們更加自然、更具可讀性:(-> hal :address :city)

可使用記錄創(chuàng)建等效的結(jié)構(gòu),如清單 8 所示:

清單 8. 使用記錄創(chuàng)建結(jié)構(gòu)

(defrecord Person [fname lname address]) (defrecord Address [street city state]) (def don (Person. "Don" "Gately"             (Address. "Ennet House" "Boston", "MA")))  (println (:fname don)) (println (-> don :address :city))

在 清單 8 中,我使用 defrecord 創(chuàng)建了相同的結(jié)構(gòu),得到了一種更加傳統(tǒng)的類結(jié)構(gòu)。借助 Clojure,可以通過(guò)熟悉的映射操作和方言在記錄結(jié)構(gòu)中實(shí)現(xiàn)同樣便捷的訪問(wèn)。

Clojure 1.2 圍繞常見(jiàn)操作的記錄定義通過(guò)兩個(gè)工廠函數(shù)添加了語(yǔ)法糖:

  • ->類型名稱, 接收字段的位置參數(shù)

  • ->映射->類型名稱, 字段值的關(guān)鍵字映射

使用符合語(yǔ)言習(xí)慣的函數(shù),代碼由清單8 轉(zhuǎn)換成版本清單 9.

清單 9. Clojure 的漂亮的語(yǔ)法糖

(def don (->Person "Don" "Gately"    (->Address "Ennet House" "Boston", "MA")))

在許多情況下,記錄比映射和扁平結(jié)構(gòu)更受歡迎。首先,defrecord 創(chuàng)建了一個(gè) Java 類,使它更容易在多方法定義中使用。然后,defrecord 指定更多任務(wù),在您定義記錄時(shí)啟用字段驗(yàn)證和其他細(xì)微處理。第三,記錄速度快得多,尤其在您擁有一組固定的已知鍵的時(shí)候。

Clojure 結(jié)合使用記錄和協(xié)議來(lái)構(gòu)造代碼。未來(lái)的一期文章將介紹它們的關(guān)系。

結(jié)束語(yǔ)

與 Java 語(yǔ)言相比,所有 3 種 Java 下一代語(yǔ)言都提供了更便捷的語(yǔ)法。Groovy 和 Scala 使構(gòu)建類和常見(jiàn)情形更加輕松,而  Clojure 使映射、記錄和類能夠無(wú)縫地互操作。所有 Java  下一代語(yǔ)言的一個(gè)共同主旨是消除不必要的樣板代碼。在下一期文章中,我將繼續(xù)探討這個(gè)主題并討論一些異常。

關(guān)于Java中Groovy、Scala和Clojure的共同點(diǎn)是什么問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。


網(wǎng)站標(biāo)題:Java中Groovy、Scala和Clojure的共同點(diǎn)是什么
本文網(wǎng)址:http://weahome.cn/article/isghii.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部