yxhxj2006

          常用鏈接

          統計

          最新評論

          Groovy入門教程

          Groovy入門教程

          kmyhy@126.com  2009-5-13

          一、groovy是什么

          簡單地說,Groovy 是下一代的java語言,跟java一樣,它也運行在 JVM 中。

          作為跑在JVM中的另一種語言,groovy語法與 Java 語言的語法很相似。同時,Groovy 拋棄了java煩瑣的文法。同樣的語句,使用groovy能在最大限度上減少你的擊鍵次數——這確實是“懶惰程序員們”的福音。

           

          二、開發環境

          1、 jdk 1.5以上

          2、 eclipse+groovy plugin(支持Groovy 1.5.7

          打開eclipse,通過Software Updates > Find and Install...菜單,使用“Search for new features to install 下載并安裝groovy插件。New一個遠程站點url可使用http://dist.codehaus.org/groovy/distributions/update/插件名Groovy plug-in。根據需要你可以同時選擇groovygrails(后續會學習到):

           

           

          三、創建groovy項目

          1、 新建一個groovy項目

          New --> Project à Java Project 創建一個java項目。為了方便管理,建議在source中建兩個source文件夾javagroovy,分別用于存儲java源文件和groovy源文件:

           

          2、 添加 Groovy 特性

          在項目上右擊,Groovy à Add Groovy Nature,這樣會在項目中添加 Groovy Libraries

           

          3、 添加 Groovy

          在項目groovy源文件下右鍵,New à Other àGroovy à Groovy Class

           

          自動生成的源代碼如下:

          public class HelloWorld{

              /**

               * @param args

               */

              public static void main(def args){

                 // TODO Auto-generated method stub

              }  

          }

          我們在main方法中加一句打印語句:

          println "Hello World"

          4、 編譯運行groovy

          在源文件上右鍵,Compile Groovy File,然后右鍵,Run As à Groovy ,在控制臺中查看運行結果。

          實際上 groovy 語法的簡練還體現在,就算整個文件中只有println "Hello World"這一句代碼(把除這一句以外的語句刪除掉吧),程序也照樣能夠運行。

          當然,為了說明groovy 其實就是java,你也可以完全按照java 語法來編寫HelloWorld類。

          四、Groovy語法簡介

          1、 沒有類型的java

          作為動態語言,groovy中所有的變量都是對象(類似于.net framework,所有對象繼承自java.lang.Object),在聲明一個變量時,groovy不要求強制類型聲明,僅僅要求變量名前使用關鍵字def(從groovy jsr 1開始,在以前的版本中,甚至連def都不需要)。

          修改main 方法中的代碼:

          def var="hello world"

          println var

          println var.class

          你可以看到程序最后輸出了var的實際類型為:java.lang.String

          作為例外,方法參數和循環變量的聲明不需要def

          2、 不需要的public

          你可以把main方法前面的public去掉實際上groovy中默認的修飾符就是public所以public修飾符你根本就不需要寫,這點跟java不一樣。

          3、 不需要的語句結束符

          Groovy中沒有語句結束符,當然為了與java保持一致性,你也可以使用;號作為語句結束符。在前面的每一句代碼后面加上;號結束,程序同樣正常運行(為了接受java程序員的頑固習慣)

          4、 字符串連接符

          java一樣,如果你需要把一個字符串寫在多行里,可以使用+號連接字符串。代碼可以這樣寫:

                 def var="hello "+

                 "world"+

                 ",groovy!"

          當然更groovy的寫法是:

                 def var="""hello

                 world

                 groovy!"""

          三個號之間不在需要+號進行連接(不過字符串中的格式符都會被保留,包括回車和tab)。

          5、 一切皆對象

          聽起來象是“眾生平等”的味道,事實上groovy對于對象是什么類型并不關心,一個變量的類型在運行中隨時可以改變,一切根據需要而定。如果你賦給它boolean ,那么不管它原來是什么類型,它接受boolean值之后就會自動把類型轉變為boolean值。看下面的代碼:

          def var="hello "+

                 "world"+

                 ",groovy!"

                 println var;

                 println var.class;

                 var=1001

                 println var.class

          輸出結果

          hello world,groovy!

          class java.lang.String

          class java.lang.Integer

           

          var這個變量在程序運行中類型在改變。一開始給它賦值String,它的類型就是String,后面給它賦值Integer,它又轉變為Integer

          6、 循環

          刪除整個源文件內容,用以下代碼替代:

                 def var="hello "+

                 "world"+

                 ",groovy!"

                 def repeat(val){

                      for(i = 0; i < 5; i++){

                       println val

                      }

                 }

                 repeat(var)

          輸出:

          hello world,groovy!

          hello world,groovy!

          hello world,groovy!

          hello world,groovy!

          hello world,groovy!

          注意循環變量i前面沒有def。當然也沒有java中常見的int,但如果你非要加上int也不會有錯,因為從Groovy1.1beta2之后開始(不包括1.1beta2),groovy開始支持java經典的for循環寫法。

          此外,上面的for語句還可以寫成:

                      for(i in 0..5)

          這樣的結果是一樣的。      

          7、 String Gstring

          除了標準的java.lang.String以外(用號括住),groovy還支持Gstring字符串類型(用號括住)。把上面的for循環中的語句改成:

                       println "This is ${i}:${val}"

          運行一下,你就會明白什么是Gstring

          8、 范圍

          這個跟pascal中的“子界”是一樣的。在前面的for循環介紹中我們已經使用過的for(i in 0..5)這樣的用法,其中的0..5就是一個范圍。

          范圍 是一系列的值。例如 0..4 表明包含 整數 01234Groovy 還支持排除范圍,“0..<4 表示 0123。還可以創建字符范圍:“a..e 相當于 abcde。“a..<e 包括小于 e 的所有值。

          范圍主要在for循環中使用。

          9、 默認參數值

          可以為方法指定默認參數值。我們修改repeat方法的定義:

          def repeat(val,repeat=3){

                      for(i in 0..<repeat){

                       println "This is ${i}:${val}"

                      }

                 }

          可以看到,repeat方法增加了一個參數repeat(并且給了一個默認值3),用于指定循環次數。

          當我們不指定第2個參數調用repeat方法時,repeat參數取默認值3

          10、              集合

          Groovy支持最常見的兩個java集合:java.util.Collectionjava.util.Map。前面所說的范圍實際也是集合的一種(java.util.List)。

          (1) Collection

          Groovy 中這樣來定義一個Collection

          def collect=["a","b","c"]

          除了聲明時往集合中添加元素外,還可以用以下方式向集合中添加元素:

          collect.add(1);

                 collect<<"come on";

                 collect[collect.size()]=100.0

          Collection使用類似數組下標的方式進行檢索:

                 println collect[collect.size()-1]

                 println collect[5]

          groovy支持負索引:

          println collect[-1]      //索引其倒數第1個元素

                 println collect[-2]      //索引其倒數第2個元素

          Collection支持集合運算:

          collect=collect+5        //在集合中添加元素5

                 println collect[collect.size()-1]

                 collect=collect-'a'         //在集合中減去元素a(1)

                 println collect[0]          //現在第1個元素變成b

          同樣地,你可以往集合中添加另一個集合或刪除一個集合:

                 collect=collect-collect[0..4]   //把集合中的前5個元素去掉

                 println collect[0]   //現在集合中僅有一個元素,即原來的最后一個元素

                 println collect[-1//也可以用負索引,證明最后一個元素就是第一個元素

          (2) Map

          Map是“鍵-值”對的集合,在groovy中,鍵不一定是String,可以是任何對象(實際上Groovy中的Map就是java.util.Linke dHashMap)

          如此可以定義一個Map:

                 def map=['name':'john','age':14,'sex':'boy']

          添加項:

                 map=map+['weight':25]       //添加john的體重

                 map.put('length',1.27)      //添加john的身高

                 map.father='Keller'         //添加john的父親

          可以用兩種方式檢索值:

                 println map['father']       //通過key作為下標索引

                 println map.length          //通過key作為成員名索引

          11、              閉包(Closure

          閉包是用{符號括起來的代碼塊,它可以被單獨運行或調用,也可以被命名。類似‘匿名類’或內聯函數的概念。

          閉包中最常見的應用是對集合進行迭代,下面定義了3個閉包對map進行了迭代:

                 map.each({key,value->    //key,value兩個參數用于接受每個元素的鍵/

                 println "$key:$value"})

                 map.each{println it}     //it是一個關鍵字,代表map集合的每個元素

                 map.each({ println it.getKey()+"-->"+it.getValue()})

          除了用于迭代之外,閉包也可以單獨定義:

          def say={word->

                     println "Hi,$word!"

                 }

          調用:

          say('groovy')

                 say.call('groovy&grails')

          輸出:

          Hi,groovy!

          Hi,groovy&grails!

           

          看起來,閉包類似于方法,需要定義參數和要執行的語句,它也可以通過名稱被調用。然而閉包對象(不要奇怪,閉包也是對象)可以作為參數傳遞(比如前面的閉包作為參數傳遞給了mapeach方法)。而在java中,要做到這一點并不容易(也許C++中的函數指針可以,但不要忘記java中沒有指針)。其次,閉包也可以不命名(當然作為代價,只能在定義閉包時執行一次),而方法不可以。

          12、             

          Groovy類和java類一樣,你完全可以用標準java bean的語法定義一個groovy 類。但作為另一種語言,我們可以使用更groovy的方式定義和使用類,這樣的好處是,你可以少寫一半以上的javabean代碼:

          (1)    不需要public修飾符

          如前面所言,groovy的默認訪問修飾符就是public,如果你的groovy類成員需要public修飾,則你根本不用寫它。

          (2)    不需要類型說明

          同樣前面也說過,groovy也不關心變量和方法參數的具體類型。

          (3)    不需要getter/setter方法

          不要奇怪,在很多ide(如eclipse)早就可以為序員自動產生getter/setter方法了。在groovy中,則徹底不需要getter/setter方法——所有類成員(如果是默認的public)根本不用通過getter/setter方法引用它們(當然,如果你一定要通過get/set方法訪問成員屬性,groovy也提供了它們)。

          (4)    不需要構造函數

          不在需要程序員聲明任何構造函數,因為groovy自動提供了足夠你使用的構造函數。不用擔心構造函數不夠多,因為實際上只需要兩個構造函數(1個不帶參數的默認構造函數,1個只帶一個map參數的構造函數由于是map類型,通過這個參數你可以在構造對象時任意初始化它的成員變量)。

          (5)    不需要return

          Groovy中,方法不需要return來返回值嗎?這個似乎很難理解。看后面的代碼吧。

          因此,groovy風格的類是這樣的:

          (6)    不需要()

          Groovy中方法調用可以省略()號(構造函數除外),也就是說下面兩句是等同的:

           

          person1.setName 'kk'
          person1.setName('kk')
           

          下面看一個完整類定義的例子:

          class Person {

           def name

           def age

           String toString(){//注意方法的類型String,因為我們要覆蓋的方法為String類型

               "$name,$age"

           }

          如果你使用javabean風格來做同樣的事,起碼代碼量要增加1倍以上。

          我們可以使用默認構造方法實例化Person類:

          def person1=new Person()

          person1.name='kk'

          person1.age=20

          println person1

          也可以用groovy的風格做同樣的事:

          def person2=new Person(['name':'gg','age':22]) //[]號可以省略

          println person2

           

          這樣需要注意我們覆蓋了ObjecttoString方法,因為我們想通過println person1這樣的方法簡單地打印對象的屬性值。

          然而toString 方法中并沒有return 一個String,但不用擔心,Groovy 默認返回方法的最后一行的值。

          13、              ?運算符

          java中,有時候為了避免出現空指針異常,我們通常需要這樣的技巧:

          if(rs!=null){

                 rs.next()

                 … …

          }

          groovy中,可以使用?操作符達到同樣的目的:

          rs?.next()

          ?在這里是一個條件運算符,如果?前面的對象非null,執行后面的方法,否則什么也不做。

          14、              可變參數

          等同于java 5中的變長參數。首先我們定義一個變長參數的方法sum

          int sum(int... var) {

          def total = 0

          for (i in var)

          total += i

          return total

          }

          我們可以在調用sum時使用任意個數的參數(1個,2個,3個……):

          println sum(1)

          println sum(1,2)

          println sum(1,2,3)

          15、              枚舉

          定義一個enum

          enum Day {

          SUNDAY, MONDAY, TUESDAY, WEDNESDAY,

          THURSDAY, FRIDAY, SATURDAY

          }

          然后我們在switch語句中使用他:

          def today = Day.SATURDAY

          switch (today) {

          //Saturday or Sunday

          case [Day.SATURDAY, Day.SUNDAY]:

          println "Weekends are cool"

          break

          //a day between Monday and Friday

          case Day.MONDAY..Day.FRIDAY:

          println "Boring work day"

          break

          default:

          println "Are you sure this is a valid day?"

          }

          注意,switchcase中可以使用任何對象,尤其是可以在case中使用List和范圍,從而使分支滿足多個條件(這點跟delphi有點象)。

          java5一樣,groovy支持帶構造器、屬性和方法的enum

          enum Planet {

          MERCURY(3.303e+23, 2.4397e6),

          VENUS(4.869e+24, 6.0518e6),

          EARTH(5.976e+24, 6.37814e6),

          MARS(6.421e+23, 3.3972e6),

          JUPITER(1.9e+27,7.1492e7),

          SATURN(5.688e+26, 6.0268e7),

          URANUS(8.686e+25, 2.5559e7),

          NEPTUNE(1.024e+26, 2.4746e7)

          double mass

          double radius

          Planet(double mass, double radius) {

          this.mass = mass;

          this.radius = radius;

          }

          void printMe() {

          println "${name()} has a mass of ${mass} " +

          "and a radius of ${radius}"

          }

          }

          Planet.EARTH.printMe()

          16、              Elvis操作符

          這是三目運算符“?:”的簡單形式,三目運算符通常以這種形式出現:

          String displayName = name != null ? name : "Unknown";

          groovy中,也可以簡化為(因為nullgroovy中可以轉化為布爾值false):

          String displayName = name ? name : "Unknown";

          基于“不重復”的原則,可以使用elvis操作符再次簡化為:

          String displayName = name ?: "Unknown"

          17、              動態性

          Groovy所有的對象都有一個元類metaClass,我們可以通過metaClass屬性訪問該元類。通過元類,可以為這個對象增加方法(在java中不可想象)!見下面的代碼,msg是一個String,通過元類,我們為msg增加了一個String 類中所沒有的方法up

          def msg = "Hello!"

          println msg.metaClass

          String.metaClass.up = {  delegate.toUpperCase() }

          println msg.up()

          通過元類,我們還可以檢索對象所擁有的方法和屬性(就象反射):

          msg.metaClass.methods.each { println it.name }

          msg.metaClass.properties.each { println it.name }

          甚至我們可以看到我們剛才添加的up方法。

          我們可以通過元類判斷有沒有一個叫up的方法,然后再調用它:

          if (msg.metaClass.respondsTo(msg, 'up')) {

              println msg.toUpperCase()

          }

          當然,也可以推斷它有沒有一個叫bytes的屬性:

          if (msg.metaClass.hasProperty(msg, 'bytes')) {

              println msg.bytes.encodeBase64()

          }

          18、              Groovy swing

          到現在為止,我們的groovy一直都在控制臺窗口下工作。如果你還不滿足,當然也可以使用swingbuilder來構建程序:

          import groovy.swing.SwingBuilder

          import java.awt.BorderLayout

          import groovy.swing.SwingBuilder

          import java.awt.BorderLayout as BL

          def swing = new SwingBuilder()

          count = 0

          def textlabel

          def frame = swing.frame(title:'Frame', size:[300,300]) {

          borderLayout()

          textlabel = label(text:"Clicked ${count} time(s).",

          constraints: BL.NORTH)

          button(text:'Click Me',

          actionPerformed: {count++; textlabel.text =

          "Clicked ${count} time(s)."; println "clicked"},

          constraints:BorderLayout.SOUTH)

          }

          frame.pack()

          frame.show()

          怎么樣?是不是跟java 中寫swing程序很象?

           

          五、單元測試

          1、 添加junit

          使用 Build PathàAdd Libraries... junit添加到項目中。

          2、 新建測試

          使用 New à Junit Test Case 新建測試例程:PersonTest,在Class under test右邊的Browser按鈕,選擇要進行測試的groovyPerson

          Finish,下面編寫測試用例代碼(我使用了Junit4):

          import org.junit.*;

          public class TestPerson {

                 @Test

                 public void testToString(){

                        Person p=new Person();              //注意因為groovy編譯Person時默認所有屬性為private

                        p.setName("ddd");                //所以用set方法設置name屬性而不用p.name=”ddd”

                        p.setAge(18);

                        Assert.assertEquals("ddd-18", p.toString());

                 }

          }

          運行Run AsàJunit Test,發現testToString通過測試。

          3、使用groovy書寫測試用例

          除了使用Java來書寫測試用例以外,我們也可以使用groovy書寫。

          New à Other à Groovy à Groovy Class,寫一個類GroovyTestPerson

          import org.junit.*;

           

          class GroovyTestPerson {

              @Test

               void testToString(){

                 Person p=new Person("name":"ddd","age":18)

                 Assert.assertEquals("ddd-18", p.toString())

              }

          }

          可以看到,這里使用的完全是Groovy風格的書寫方式:不需要public,使用map參數構造對象。然而當你Run AsàJunit Test的時候,結果跟用java編寫的測試用例沒有什么兩樣。

          這也充分說明了,groovyjava,除了語法不一樣,本質上沒有什么區別(對比.net framework中的C#VB.net,它們除了語法不同外,本質上它們都使用CLR)。

          posted on 2014-04-25 23:23 奮斗成就男人 閱讀(215) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 临潭县| 佛山市| 竹山县| 长丰县| 洛扎县| 离岛区| 嘉定区| 浏阳市| 融水| 昌邑市| 宁远县| 常宁市| 永顺县| 昌吉市| 元江| 松溪县| 榆社县| 敖汉旗| 漳平市| 新绛县| 巫山县| 昂仁县| 衡山县| 威海市| 罗城| 名山县| 晋州市| 马龙县| 定远县| 凌海市| 平乐县| 泽州县| 浦城县| 阳曲县| 惠来县| 天柱县| 满洲里市| 陆川县| 甘德县| 三原县| 扎囊县|