groovy比起java,有哪些地方寫起來更舒服

java發展緩慢,語法落後冗餘

提及java,其實java挺好的,java如今的性能也不錯,可是,java的語法顯然比較落後,並且冗餘,getter/setter之類的,5的泛型 for each,autobox,7的鑽石語法,try catch 多個exception,8的lambda,總之發展緩慢,9也跳票了.html

groovy 是什麼,有哪些特性

groovy是一個可選的動態類型語言,有靜態編譯的能力.在我看來,groovy寫起來很舒服,有一些動態語言的優點,並且,它和java是100%兼容的,若是你使用靜態編譯,那麼幾乎全部的特性也能和java互掉java

先來幾個耳目一新的特性

int a=1//不須要分號
        String multiLine='''
1//適應osc的markdwon
2//適應osc的markdwon
3'''//多行字符串
        def map=[a:1,b:2]//這是個map
        def list=[1,2,3,4,5]//這是個list
        def range=1..5//這是個range
        // null 空集合(包含map) 0 空字符串 空數組 在boolean環境中是false
        def aMap=[:]
        if (aMap){//groovy的false值,上面也提過
            println('這段代碼不會被執行')//aMap意味着false
        }
        String interpolationString="$map or ${map}"//這是插值字符串,基本現代的語言都有吧
        map << ['c':3]//這是重載運算符,實現起來其實很簡單

好了,先從這幾個小特性提及,兩個語言的對比範疇很大,但本文主要從語法的便利性角度入手,告訴你爲何groovy寫着舒服spring

1 可選分號;

大部分人可能以爲就是少寫個分號而已,我列到第一,大驚小怪.可是實際上我告訴你,你寫了那麼多年的分號白寫了,實在沒啥用,kotlin已經列爲可選了,我以爲這也算是現代語言的標誌之一,去掉舊時代的冗餘語法sql

分號沒用,由於你們寫java,基本都一行一句,不必加分號,編譯器本身加就完了(一行多句仍是要本身加),不加分號也不影響代碼的可讀性,實際上徹底不影響.我見到的現代語言中,rust須要分號來結尾,可是rust的分號是用來區別句子和表達式的,加分號是語句,不加分號是表達式(有返回值),是有真正的需求來區分語義的,可是java顯然不須要.<br>apache

你java打了那麼多年的分號,實際不須要,是浪費時間,我寫js的時候也不打分號,固然js的不打分號是有潛在的坑的,你須要知道,不過我這裏很少說了json

2 多行字符串和插值字符串

實際上,這是一種很迫切的需求,惋惜java就沒有
好比我用spring jdbc,寫sql的時候,我須要很長的sql,並且這個sql我就用一次,很特殊,(不必用mybatis的方式抽出去),這個時候,我想怎麼換行,就怎麼換行,很隨意的.至於插值,這個明顯節約代碼量,省工.
'string'單引號閉合是String,"string${aaa}"雙引號閉合是GString,支持插值,目前知道這些就行了
我想,這也是java的mybatis之類的流行的一個緣由吧,java不支持多行字符串,因此代碼裏面寫sql有些虐數組

3 友好的map和list操做,本身看代碼就清楚了

def numList = [1, 2, 3, 4, 5]//很方便,等價List numList=new ArrayList();numList.add(1) ... 其實這個實現很簡單,可是java也許就是不肯意作吧
        def numMap = [a: 1, b: 2, c: 3]//很方便,等價也很方便
        def list = [] //默認是ArrayList
        assert list.class == ArrayList//能夠省略.class
        def map = [:] //默認是LinkedHashMap,爲何不是{},而是[:],官方的解釋就是{}和閉包還有語句的大括號衝突了,不過這也沒什麼
        assert map.class == LinkedHashMap
        map.'a' = 1
        map.b = 2
        map << [c: 3]
        assert map == [a: 1, b: 2, c: 3]
        assert map.a == 1
        assert map.'a' == 1//map 包含空白字符之類的能夠用這種方式
        assert map['a'] == 1//map 包含空白字符之類的能夠用這種方式
        list.add(1)
        list << 2
        assert list == [1, 2]
        assert list[0] == 1
        LinkedList list1 = []//由於默認是ArrayList,這種方式能夠改變
        assert list1.class == LinkedList
        def list2 = [:] as LinkedList//另一種方式改變
        assert list2.class == LinkedList

def 我之後會講,你暫時須要知道的就是,你雖然用的是def,可是其實編譯器知道numList 是List<Integer>,是的,包含泛型,在@CompileStatic或@TypeChecked的模式下,意味着numList .add('3')會出錯mybatis

4 友好的操做符重載

如今先給你一個java的驚喜閉包

Integer a = 1;
        System.out.println(a == 1);//true無疑
        BigDecimal b1 = new BigDecimal(1);
        BigDecimal b2 = new BigDecimal(1);
        b2.setScale(1);
        System.out.println(b1 == b2);//居然是false,好吧,這是對象引用的比較
        System.out.println(b1.equals(b2));//是true
        System.out.println(b1.compareTo(b2));//或許你須要用這個

換成groovy框架

BigDecimal a = 1
        BigDecimal b = a + 1 - 1
        b = b + 2 //還能夠這樣寫
        assert a == b//==被映射爲equals
        //用原來的== 能夠用 .is
        assert !(a.is(b))
        int i = 1
        if (i) {//其實(i)也是運算符重載,此時會調用i的asBoolean()方法,由於groovy會autobox基本類型
            println('我會被執行,由於i==1,數字除了0都是true')
        }

更多的重載運算符 重載運算符

5 去掉冗餘的老舊的getter setter

groovy提出了新的概念properties,不是java的filed

class Pro {
    Integer property1 //1 沒用private public protected(gorrvy裏面是@PackageScope)
    def property2   //2 可選的statoc final(有final就會沒有set) 之類的
    final String property3  //3 def 或者 肯定的類型
    static String property4 //4 property名字
    //知足以上四個條件就是一個property
    
    //實際上等於java如下內容,一個private+getter+setter(final修飾的沒有setter)
    private String property5

    String getProperty5() {
        return property5
    }

    void setProperty5(String property5) {
        this.property5 = property5
    }
}

groovy提出了property的概念,並且其實現也好java兼容,可是碼量明顯減小,其'.'的語法是GPath,會自動調用get

static void main(String[] args) {
        def pro = new Pro()
        Pro pro1 = [:]//也能夠這樣聲明,前提是必須指定類型,而且有默認的構造器,如下等價
        Pro pro2 = []//等價以上
        Pro pro3 = [property1: 123]//等價以上
        def pro4 = [property1: 123] as Pro//等價以上
        pro.property1 = 123 //相似pro.setProperty1(123)
        println(pro.property1)//相似pro.getProperty1()
    }

6 動態語言的溫馨,靜態語言的性能

groovy 1的是時候,有人詬病性能不佳,可是groovy 2開始,提供了@TypeChecked註解,靜態檢查,有時須要其餘的註解來支持,@CompileStatic,靜態檢查+靜態編譯,此時會失去groovy的動態特性,並且此時的grrovy幾乎能實現和java 100%的互掉(不僅是groovy 調用java,java 調用groovy 也同樣)

做爲靜態語言的喜好者,明顯是不用def,雖然groovy是可選的類型.官方的文檔也說到,如今動態也很快了,甚至有些時候比靜態都快,可是我不太信,我沒看到數據的對比.使用groovy,你能夠用現代的語法,和相似動態語言的便利,寫出和靜態語言幾乎同樣的性能

@CompileStatic//開啓靜態編譯
class CompileStaticDemo {
    static void main(String[] args) {
        String s = '123'//雖然你用def,編譯器也知道s是String,可是這不利於代碼的閱讀,因此仍是老老實實的用明確的類型
        assert s.length() == 3
        Closure square = { int x ->
            return x * x
        }
        assert 9 == square(3)
        Pro pro = []
        assert pro.property1 == null
        //這點就是徹底有靜態語言的寫法,並且編譯成靜態的代碼
    }
}

我的人

7 豐富的內置支持,例如json

實際上groovy仍是造了不少輪子的,好比groovy的模板,groovy版的jsp,交gsp,groovy內置的xml支持等等,這些輪子無疑會增長成本,可是不少咱們能夠不用,忽略便可

不過這個內置json,仍是要提一下,這個內置json是整合的boon json,很早的一個評測,2013年的,boon json和其它框架的benchmark 那時候boon json的性能居然大部分狀況好於jackson

無論怎麼說,java從5支持正則,沒有之前,java用正則要用jakarta 的正則包,你用groovy了之後,如今就能夠用內置的json支持,仍是很便利的

@CompileStatic
class JsonDemo {
    static void main(String[] args) {
        Pro pro = []
        pro.property1 = 123
        pro.property2 = 'property2'
        pro.property5 = '555'
        def json = JsonOutput.toJson(pro)
        println(json)//{"property5":"555","property2":"property2","property4":null,"property1":123,"property3":null}
        //null 值沒有忽略,groovy 2.5 中會添加支持,不斷完善中
    }
}

個人實踐

groovy是一個動態語言,可是2.0之後,能夠做爲靜態語言來用,我以爲grrovy的動態特性可能主要是用來支持groovy DSL的,對於服務端的程序來講,我認爲不必用它動態的特性.

可是每個類都加@CompileStatic實在太麻煩,不過groovy提供了一個特性.自定義CompilerConfiguration ,你寫一個腳本

package conf
//換行
withConfig(configuration) {
    ast(groovy.transform.CompileStatic)
}

而後用下面的編譯,就行了

groovyc -configscript src/conf/config.groovy src/main/groovy/MyClass.groovy

固然咱們的項目沒那麼簡單,你用idea的話,能夠配置這個Config script flag,用gradle的話,雖然我沒試過,可是我以爲也有相似的配置吧,因此你能夠放心的用groovy的CompileStatic

用它代替java沒問題

1. 穩定的支持,發展好

groovy比起java,糖多,寫起來舒服,可是一個企業用的技術,必須是LTS,5年甚至10年都要有技術支持,這點grrovy能行嗎,實際上groovy 2.0之後,愈來愈好了,如今已經就入了apache,即便加入apache以前,也得到過商業公司Pivotal軟件的支持,2015年3月,groovy加入的apache

這是tiobe的走勢 tiobe中groovy的走勢 也能夠說明groovy的流行程度愈來愈高 tiobe groovy走勢

2. 沒有什麼不可忍受的缺點

語法沒什麼蹩腳的地方,這點和kotlin比比

val a: Int = 1  // immediate assignment
val b = 2   // `Int` type is inferred
val c: Int  // Type required when no initializer is provided
c = 3       // deferred assignment

我只想說,爲啥不 int a =1 ,即便你能類型自動推測var a =1 也不利於閱讀,並且冒號也沒有空格好敲,不過,這個能夠忍,
若是寫成下面這段代碼就更有意思了
好多var
你看到一大堆var的時候有何感想

3. 徹底能夠靜態檢查編譯

雖然它是動態類型,可是徹底當靜態用沒問題,這點既保障了性能,也保證了代碼質量,上面已經提過了.固然用不用groovy,這個取決與你是否喜歡它,認爲他比java好,寫起來更舒服

4. groovy即java,不缺輪子

java的生態groovy徹底能夠無縫繼承,並且靜態編譯的groovy幾乎也能夠被java 100%互掉,因此輪子都是現成的,徹底不缺

5. "0成本"的學習曲線

比起scala之流,groovy和java的類似度仍是很大的,學習起來比較easy的,基本上基礎學幾下,用起來就沒什麼問題了,不過你仍是須要一段時間來適應

相關文章
相關標籤/搜索