Groovy新手教程

Groovy新手教程java

kmyhy@126.com  2009-5-13數組

1、groovy是什麼閉包

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

做爲跑在JVM中的還有一種語言,groovy語法與 Java 語言的語法很是相似。同一時候,Groovy 拋棄了java煩瑣的文法。相同的語句,使用groovy能在最大限度上下降你的擊鍵次數——這確實是「懶惰程序猿們」的福音。ide

 

2、開發環境函數

一、  jdk 1.5以上學習

二、  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(興許會學習到):ui

 

 

3、建立groovy項目this

一、  新建一個groovy項目

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

 

二、  加入 Groovy 特性

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

 

三、  加入 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"

四、  編譯執行groovy

在源文件上右鍵,Compile Groovy File,而後右鍵,Run As à Groovy ,在控制檯中查看執行結果。

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

固然,爲了說明groovy 事實上就是java,你也可以全然依照java 語法來編寫HelloWorld類。

4、Groovy語法簡單介紹

一、  沒有類型的java

做爲動態語言,groovy中所有的變量都是對象(類似於.net framework,所有對象繼承自java.lang.Object),在聲明一個變量時,groovy不要求強制類型聲明,只要求變量名前使用keyworddef(從groovy jsr 1開始,在曾經的版本號中,甚至連def都不需要)。

改動main 方法中的代碼:

def var="hello world"

println var

println var.class

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

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

二、  不需要的public

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

三、  不需要的語句結束符

Groovy中沒有語句結束符,固然爲了與java保持一致性,你也可以使用;號做爲語句結束符。在前面的每一句代碼後面加上;號結束,程序相同正常執行(爲了接受java程序猿的頑固習慣)

四、  字符串鏈接符

java同樣,假設你需要把一個字符串寫在多行裏,可以使用+號鏈接字符串。代碼可以這樣寫:

       def var="hello "+

       "world"+

       ",groovy!"

固然更groovy的寫法是:

       def var="""hello

       world

       groovy!"""

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

五、  一切皆對象

聽起來象是「衆平生等」的味道,其實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

六、  循環

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

       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)

這種結果是同樣的。      

七、  String Gstring

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

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

執行一下,你就會明確什麼是Gstring

八、  範圍

這個跟pascal中的「子界」是同樣的。在前面的for循環介紹中咱們已經使用過的for(i in 0..5)這種使用方法,當中的0..5就是一個範圍。

範圍 是一系列的值。好比 0..4 代表包括 整數 01234Groovy 還支持排除範圍,「0..<4 表示 0123。還可以建立字符範圍:「a..e 至關於 abcde。「a..<e 包括小於 e 的所有值。

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

九、  默認參數值

可以爲方法指定默認參數值。咱們改動repeat方法的定義:

def repeat(val,repeat=3){

            for(i in 0..<repeat){

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

            }

       }

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

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

十、              集合

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做爲成員名索引

十一、              閉包(Closure

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

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

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

       println "$key:$value"})

       map.each{println it}     //it是一個keyword,表明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中,要作到這一點並不easy(或許C++中的函數指針可以,但不要忘記java中沒有指針)。其次,閉包也可以不命名(固然做爲代價,僅僅能在定義閉包時運行一次),而方法不可以。

十二、             

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 默認返回方法的最後一行的值。

1三、              ?運算符

java中,有時候爲了不出現空指針異常,咱們一般需要這種技巧:

if(rs!=null){

       rs.next()

       … …

}

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

rs?.next()

?在這裏是一個條件運算符,假設?前面的對象非null,運行後面的方法,不然什麼也不作。

1四、              可變參數

等同於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)

1五、              枚舉

定義一個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()

1六、              Elvis操做符

這是三目運算符「?:」的簡單形式,三目運算符一般以這樣的形式出現:

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

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

String displayName = name ? name : "Unknown";

基於「不反覆」的原則,可以使用elvis操做符再次簡化爲:

String displayName = name ?: "Unknown"

1七、              動態性

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()

}

1八、              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程序很是象?

 

5、單元測試

一、  加入junit

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

二、  新建測試

使用 New à Junit Test Case 新建測試例程:PersonTest,在Class under test右邊的Browserbutton,選擇要進行測試的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)。

相關文章
相關標籤/搜索