- 一、什么是Groovy?
- ?????Groovy?是?JVM?的一个替代语言?—?替代?是指可以用?Groovy?在?Java?平台上进行?Java?编程,使用方式基本与使用?Java?代码的方式相同。注意:不是指Groovy替代java,而是指Groovy和java很好的结合编程?
- ●?是一个基于?Java虚拟机的敏捷?动态语言。?
- ●?构建在强大的Java语言之上?并?添加了从Python,Ruby和Smalltalk等语言中学到的?诸多特征。?
- ●?为Java开发者提供了?现代最流行的编程语言特性,而且学习成本很低(几乎为零)。?
- ●?支持DSL(Domain?Specific?Languages领域定义语言)和其它简洁的语法,让你的代码变得易于阅读和维护。?
- ●?Groovy拥有处理原生类型,面向对象以及一个Ant?DSL,使得创建Shell?Scripts变的非常简单。?
- ●?在开发Web,GUI,数据库或控制台程序时?通过?减少框架性代码?大大提高了开发者的效率。?
- ●?支持单元测试和模拟(对象),可以?简化测试。?
- ●?无缝集成?所有已经存在的?Java对象和类库。?
- ●?直接编译成Java字节码,这样可以在任何使用Java的地方?使用Groovy。?
- Groovy?的一个好处是,它的语法与?Java?语言的语法很相似。虽然?Groovy?的语法源于?Smalltalk?和?Ruby?这类语言的理念,但是可以将它想像成?Java?语言的一种更加简单、表达能力更强的变体。(在这点上,Ruby?与?Groovy?不同,因为它的语法与?Java?语法差异很大。)?
- 许多?Java?开发人员非常喜欢?Groovy?代码和?Java?代码的相似性。从学习的角度看,如果知道如何编写?Java?代码,那就已经了解?Groovy?了。Groovy?和?Java?语言的主要区别是:完成同样的任务所需的?Groovy?代码比?Java?代码更少。(有时候会少很多!)??
- ?
- 二、开发环境?
- 1.?jdk1.6?
- 2.?eclipse+groovy?plugin(3.7)?
- 打开eclipse,通过?Help->Install?New?Software,下载并安装groovy插件。?New一个远程站点,?url可以使用?groovy?-?http:?
- 三、新建Groovy项目?
- 1、新建Groovy项目?
- 2、添加Groovy?Libraries?
- 3、添加Groovy?Class,自动生成Main方法,在方法中添加一句代码“println?"Hello?World"”,右键运行,在控制台上输出“Hello?World”。?
- 四、Groovy语法简介?
- 1、没有类型的Java?
- 作为动态语言,groovy中所有的变量都是对象(类似.net?framework,?所有对象继承自java.lang.Object),在声明一个变量时,groovy不要求强制类型声明,仅仅要求变量名前使用关键字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"?
- 当然更可以这样写?
- 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?
- ????????println?var.class?
- ????????var=false?
- ????????println?var?
- ????????println?var.class?
- 输出结果是?
- hello?world,groovy?
- class?java.lang.String?
- 1001?
- class?java.lang.Integer?
- false?
- class?java.lang.Boolean?
- var这个变量在程序运行中,类型在改变。一开始给它赋值String,它的类型就是String,后来给它赋值Integer,它的类型就是Integer,最后给它赋值Boolean,它的类型就是Boolean。?
- 6、循环?
- 删除源文件下的所有内容,用一下内容代替?
- static?void?main(String[]?args)?{?
- ?????????
- ????????def?var?=?"hello?"?+?
- ????????"world"?+?
- ????????",groovy"?
- ????????repeat(var)?
- ????}?
- ?????
- ????def?static?repeat(val)?{?
- ????????for(i=0;i<5;i++)?{?
- ????????????println?val?
- ????????}?
- ????}?
- 输出结果是:?
- hello?world,groovy?
- hello?world,groovy?
- hello?world,groovy?
- 注意循环变量i前面没有def。当然也没有java中常见的int,但是如果你非要加上int也不会有错,因为Groovy?1.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}"?
- 输出:?
- This?is?0:?hello?world,groovy?
- This?is?1:?hello?world,groovy?
- This?is?2:?hello?world,groovy?
- This?is?3:?hello?world,groovy?
- This?is?4:?hello?world,groovy?
- 8、范围?
- 在前面的for循环介绍中我们已经使用过的for(i?in?0..5)?这样的用法,其实就是一个范围。?
- 范围是一系列值。例如“0..4”表示包含整数0、1、2、3、4.Groovy还支持排除范围,“0..<4”表示0、1、2、3.还可以创建字符范围:“a..e”相当于a、b、c、d、e。“a..<e”包括小于e的值。?
- 9、默认参数值?
- 还可以为方法指定默认参数值。修改repeat方法的定义:?
- def?static?repeat(val,?repeatNum=3)?{?
- ????????for(i?in?0..<repeatNum)?{?
- ????????????println?"This?is?${i}:?${val}"?
- ????????}?
- ????}?
- 可以看到,repeat方法增加了一个参数repeatNum(并给了一个默认值3),用于指定循环次数。当我们不指定第二个参数调用repeat方法时,repeatNum参数取默认值。?
- 10、集合?
- Groovy支持最常见的两个java集合:java.util.Collection和java.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使用类似数组下标的方式进行检索:?
- collect[collect.size()-1]?
- collect[5]?
- groovy支持负索引:?
- ????????println?collect[-1]???
- ????????println?collect[-2]???
- Collection支持集合运算:?
- ????????collect=collect+5???????
- ????????println?collect[-1]?????
- ????????collect=collect-"a"?????
- ????????println?collect[0]??????
- 同样地,可以往集合中添加另一个集合或删除一个集合:?
- collect=collect-collect[0..4]??
- ????????println?collect[0]?????????????
- ????????println?collect[-1]????????????
- (2)Map?
- Map是“键-值”对的集合,在groovy中,键不一定是String,可以是任何对象(实际上Groovy中的Map就是java.util.LinkedHashMap)。?
- 如此可以定义一个Map:?
- def?map=['name':'john','age':14,'sex':'boy']?
- 添加项:?
- map=map+['weight':25]??????
- map.put('hight',?1.27)?????
- map.father='Keller'????????
- 可以用两种方式检索值:?
- println?map['father']??????
- println?map.hight?????????
- 11、闭包(Closure)?
- 闭包是用{符号括起来的代码块,它可以被单独运行或调用,也可以被命名。类似‘匿名类’或内联函数的概念。?
- 闭包中最常见的应用是对集合进行迭代,下面定义了闭包对map进行了迭代:?
- map.each?({key,value->println?"$key:$value"})???
- map.each?{println?it}???????????????????????????
- 除了用于迭代之外,闭包可以单独定义:?
- def?say={word->?println?"Hi,?$word!"}?
- 调用:?
- ????????say("groovy")?
- ????????say.call("groovy?&?java")?
- 输出:?
- Hi,?groovy!?
- Hi,?groovy?&?java!?
- 看起来,闭包类似于方法,需要定义参数和要执行的语句,它也可以通过名称被调用。然而闭包对象(不要奇怪,闭包也是对象)可以作为参数传递(比如前面的闭包作为参数传递给map的each方法)。而在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方法引用它们(当然,如果你一定要通过getter/setter方法访问成员属性,Groovy也提供了它们)。?
- (4)不需要构造函数?
- 不再需要程序员声明任何构造函数,因为实际上只需要两个构造函数(1个不带参数的默认构造函数,1个只带一个map参数的构造函数--由于是map类型,通过这个参数你可以构造对象时任意初始化它的成员变量)。?
- (5)不需要return?
- Groovy中,方法不需要return来返回值吗?这个似乎很难理解,看后面的代码吧,因此,Groovy风格的类是这样的?
- (6)不需要()?
- Groovy中方法调用?可以省略()(构造函数除外),也就是说下面两名是等同的:?
- ????????def?person1?=?new?Person()?
- ????????person1.setName?"john"?
- ????????person1.setAge(25)?
- 下面看一个完整类定义的例子:?
- class?Person?{?
- ????def?name?
- ????def?age?
- ????String?toString()?{??
- ????????"$name,?$age"?
- ????}?
- 如果你使用javabean风格来做同样的事,起码代码量要增加1倍以上。?
- 我们可以使用默认构造方法实例化Person类:?
- ????????def?person1?=?new?Person()?
- ????????person1.setName?"john"?
- ????????person1.setAge(25)?
- 也可以用Groovy的风格做同样的事:?
- def?person2=new?Person(['name':'john','age':25])?????
- println?person2?
- 这样需要注意我们覆盖了Object的toString方法,因为我们想通过println?person1这样的方法简单地打印对象的属性值。?
- 然而toString方法中并没有return一个String,但不用担心,Groovy默返回方法的最后一行的值。?
- 13、?运算符?
- 在java中,有时候为了避免出现空指针异常,我们通常需要这样的技巧:?
- if(rs!=null)?{?
- ????????????rs.next()?
- ????????????......?
- ????????}?
- 在Groovy中,可以使用?操作符达到同样的目的:?
- rs?.next()?
- ?在这里是一个条件运算符,如果?前面的对象非null,执行后面的方法,否则什么也不做。?
- 14、可变参数?
- 等同于java5中的变长参数。首先我们定义一个变长参数的方法sum:?
- ????int?sum(int...?var)?{?
- ????????def?total=0?
- ????????for(i?in?var)?{?
- ????????????total+=1?
- ????????}?
- ????????????return?total?
- ????}?
- 我们可以调用sum时使用任意个的参数(1个,2个,3个……):?
- ????????println?sum(1)???????
- ????????println?sum(1,2)?
- ????????println?sum(1,2,3)?
- 15、枚举?
- 定义一个enum:?
- ????????def?today=Day.SATURDAY?
- ????????switch(today)?{?
- ?????????????
- ????????????case?[Day.SATURDAY,?Day.SUNDAY]:?
- ????????????println?"Weekends?are?cool"?
- ????????????break;?
- ????????????case?Day.MONDAY..Day.FRIDAY:?
- ????????????println?"Boring?work?day"?
- ????????????break;?
- ????????????default:?
- ????????????println?"Are?you?sure?this?is?a?valid?day?"?
- ????????}?
- 注意,switch和case中可以使用任何对象,尤其是可以在case中使用List和范围,从而使分支满足多个条件。?
- 同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中,也可以简化为(因为null在Groovy中可以转化为布尔值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?
- ????????println?msg.metaClass??
- ????????String.metaClass.up={delegate.toUpperCase()}?
- ????????println?msg.up()?
- 通过元类,我们还可以检索对象所拥有的方法和属性(就是反射):?
- msg.metaClass.metaMethods.each?{println?it.name}?
- ????????msg.metaClass.properties.each?{?println?it.name}?
- 甚至我们可以看到我们刚才添加的up方法。?
- 我们可以通过元类判断有没有一个叫up的方法,然后再调用它:?
- if?(msg.metaClass.respondsTo(msg,?'up'))?{?
- ????????????println?msg.up()?
- ????????}?
- 当然,也可以推断它有没有一个叫bytes的属性:?
- ????????if(msg.metaClass.hasProperty(msg,?'bytes'))?{?
- ????????????println?msg.bytes.encodeBase64()?
- ????????}?