1. 一、什么是Groovy 
  2.      Groovy 是 JVM 的一个替代语言 — 替代 是指可以用 Groovy 在 Java 平台上进行 Java 编程,使用方式基本与使用 Java 代码的方式相同。注意:不是指Groovy替代java,而是指Groovy和java很好的结合编程 
  3.   ● 是一个基于 Java虚拟机的敏捷 动态语言。 
  4.   ● 构建在强大的Java语言之上 并 添加了从Python,Ruby和Smalltalk等语言中学到的 诸多特征。 
  5.   ● 为Java开发者提供了 现代最流行的编程语言特性,而且学习成本很低(几乎为零)。 
  6.   ● 支持DSL(Domain Specific Languages领域定义语言)和其它简洁的语法,让你的代码变得易于阅读和维护。 
  7.   ● Groovy拥有处理原生类型,面向对象以及一个Ant DSL,使得创建Shell Scripts变的非常简单。 
  8.   ● 在开发Web,GUI,数据库或控制台程序时 通过 减少框架性代码 大大提高了开发者的效率。 
  9.   ● 支持单元测试和模拟(对象),可以 简化测试。 
  10.   ● 无缝集成 所有已经存在的 Java对象和类库。 
  11.   ● 直接编译成Java字节码,这样可以在任何使用Java的地方 使用Groovy。 
  12.   Groovy 的一个好处是,它的语法与 Java 语言的语法很相似。虽然 Groovy 的语法源于 Smalltalk 和 Ruby 这类语言的理念,但是可以将它想像成 Java 语言的一种更加简单、表达能力更强的变体。(在这点上,Ruby 与 Groovy 不同,因为它的语法与 Java 语法差异很大。) 
  13.   许多 Java 开发人员非常喜欢 Groovy 代码和 Java 代码的相似性。从学习的角度看,如果知道如何编写 Java 代码,那就已经了解 Groovy 了。Groovy 和 Java 语言的主要区别是:完成同样的任务所需的 Groovy 代码比 Java 代码更少。(有时候会少很多!)  
  14.  
  15. 二、开发环境 
  16. 1. jdk1.6 
  17. 2. eclipse+groovy plugin(3.7
  18. 打开eclipse,通过 Help->Install New Software,下载并安装groovy插件。 New一个远程站点, url可以使用 groovy - http://dist.codehaus.org/groovy/distributions/greclipse/snapshot/e3.7/,选择安装groovy插件。 
  19. 三、新建Groovy项目 
  20. 1、新建Groovy项目 
  21. 2、添加Groovy Libraries 
  22. 3、添加Groovy Class,自动生成Main方法,在方法中添加一句代码“println "Hello World"”,右键运行,在控制台上输出“Hello World”。 
  23. 四、Groovy语法简介 
  24. 1、没有类型的Java 
  25. 作为动态语言,groovy中所有的变量都是对象(类似.net framework, 所有对象继承自java.lang.Object),在声明一个变量时,groovy不要求强制类型声明,仅仅要求变量名前使用关键字def。 
  26. 修改main方法中和代码: 
  27. def var="hello world" 
  28. println var 
  29. println var.class 
  30. 就可以看到程序最后输出了var的实际类型为java.lang.String 
  31. 作为例外,方法参数和循环变量的不需要def。 
  32. 2、不需要的public 
  33. 你可以把main方法前面的public去掉,实际上groovy中默认的修饰符就是public所以public修饰符根本就不需要写,这点和java不一样。 
  34. 3、不需要的语句结束符 
  35. Groovy中没有语句结束符,当然为了和java保持一致,也可以使用;号作为语句结束符。在前面的每一句代码后面加上;号结束,程序同样正常运行(为了接受java程序员的顽固习惯)。 
  36. 4、字符串连接符 
  37. 跟java一样,如果需要把一个字符串写在多行里,可以使用+号连接字符串,代码可以这样写: 
  38. def var = "hello " + 
  39.         "world" + 
  40.         ",groovy" 
  41. 当然更可以这样写 
  42. def var = """hello  
  43. world  
  44. groovy!""
  45. 三个"号之间不再需要+号进行连接(不过字符串中的格式都会被保留,包括回车和tab)。 
  46. 5、一切皆对象 
  47. 听起来像是“众生平等”的味道,事实上groovy对于对象是什么类型并不关心,一个变量的类型在运行中随时可以改变,一切根据需要而定。如果你赋值给它boolean,那么不管它原来是什么类型,它接受boolean值之后就会自动把类型转变为boolean值。看下面的代码: 
  48.     def var = "hello " + 
  49.         "world" + 
  50.         ",groovy" 
  51.         println var 
  52.         println var.class 
  53.         var=1001 
  54.         println var 
  55.         println var.class 
  56.         var=false 
  57.         println var 
  58.         println var.class 
  59. 输出结果是 
  60. hello world,groovy 
  61. class java.lang.String 
  62. 1001 
  63. class java.lang.Integer 
  64. false 
  65. class java.lang.Boolean 
  66. var这个变量在程序运行中,类型在改变。一开始给它赋值String,它的类型就是String,后来给它赋值Integer,它的类型就是Integer,最后给它赋值Boolean,它的类型就是Boolean。 
  67. 6、循环 
  68. 删除源文件下的所有内容,用一下内容代替 
  69. static void main(String[] args) { 
  70.          
  71.         def var = "hello " + 
  72.         "world" + 
  73.         ",groovy" 
  74.         repeat(var) 
  75.     } 
  76.      
  77.     def static repeat(val) { 
  78.         for(i=0;i<5;i++) { 
  79.             println val 
  80.         } 
  81.     } 
  82. 输出结果是: 
  83. hello world,groovy 
  84. hello world,groovy 
  85. hello world,groovy 
  86. hello world,groovy 
  87. hello world,groovy 
  88. 注意循环变量i前面没有def。当然也没有java中常见的int,但是如果你非要加上int也不会有错,因为Groovy 1.1beta2之后开始(不包含1.1beta2),groovy开始支持java经典的for循环写法。 
  89. 此外,上面的for语句还可以写成: 
  90.     for(i in 0..<5)  
  91. 这样的结果是一样的。 
  92. 7、String和Gstring 
  93. 除了标准的java.lang.String以外,groovy还支持Gstring字符类型。把上面的for循环中的语句换成: 
  94.     println "This is ${i}: ${val}" 
  95. 输出: 
  96. This is 0: hello world,groovy 
  97. This is 1: hello world,groovy 
  98. This is 2: hello world,groovy 
  99. This is 3: hello world,groovy 
  100. This is 4: hello world,groovy 
  101. 8、范围 
  102. 在前面的for循环介绍中我们已经使用过的for(i in 0..5) 这样的用法,其实就是一个范围。 
  103. 范围是一系列值。例如“0..4”表示包含整数01234.Groovy还支持排除范围,“0..<4”表示0123.还可以创建字符范围:“a..e”相当于a、b、c、d、e。“a..<e”包括小于e的值。 
  104. 9、默认参数值 
  105. 还可以为方法指定默认参数值。修改repeat方法的定义: 
  106. def static repeat(val, repeatNum=3) { 
  107.         for(i in 0..<repeatNum) { 
  108.             println "This is ${i}: ${val}" 
  109.         } 
  110.     } 
  111. 可以看到,repeat方法增加了一个参数repeatNum(并给了一个默认值3),用于指定循环次数。当我们不指定第二个参数调用repeat方法时,repeatNum参数取默认值。 
  112. 10、集合 
  113. Groovy支持最常见的两个java集合:java.util.Collection和java.util.Map。前面所说的范围实际也是一种(java.util.List)。 
  114. (1)Collection 
  115. Groovy中这样来定义一处collection: 
  116. def collect=["a","b","c"
  117. 除了声明时往集合中添加元素外,还可以用以下方式向集合中添加元素: 
  118.  
  119. collect.add(1); 
  120. collect<<"Come on" 
  121. collect[collect.size()]=100.0 
  122. Collection使用类似数组下标的方式进行检索: 
  123. collect[collect.size()-1
  124. collect[5
  125. groovy支持负索引: 
  126.         println collect[-1]  //索引倒数第1个元素 
  127.         println collect[-2]  //索引倒数第2个元素 
  128. Collection支持集合运算: 
  129.         collect=collect+5      //在集合中添加元素5 
  130.         println collect[-1]    //索引倒数第1个元素 
  131.         collect=collect-"a"    //在集合中减去元素a(第1个) 
  132.         println collect[0]     //索引集合中第1个元素(现在是b) 
  133. 同样地,可以往集合中添加另一个集合或删除一个集合: 
  134. collect=collect-collect[0..4//把集合中的前5个元素去掉 
  135.         println collect[0]            //现在集合中只有1个元素,即原来最后一个 
  136.         println collect[-1]           //也可以用负索引,证明最后一个元素就是第一个元素 
  137. 2)Map 
  138. Map是“键-值”对的集合,在groovy中,键不一定是String,可以是任何对象(实际上Groovy中的Map就是java.util.LinkedHashMap)。 
  139. 如此可以定义一个Map: 
  140. def map=['name':'john','age':14,'sex':'boy'
  141. 添加项: 
  142. map=map+['weight':25]     //添加john的体重     
  143. map.put('hight'1.27)    //添加john的身高 
  144. map.father='Keller'       //添加john的父亲    
  145. 可以用两种方式检索值: 
  146. println map['father']     //通过key索引下标索引 
  147. println map.hight        //通过key作为成员名索引 
  148. 11、闭包(Closure) 
  149. 闭包是用{符号括起来的代码块,它可以被单独运行或调用,也可以被命名。类似‘匿名类’或内联函数的概念。 
  150. 闭包中最常见的应用是对集合进行迭代,下面定义了闭包对map进行了迭代: 
  151. map.each ({key,value->println "$key:$value"})  //key,value两个参数用于接受每个元素 
  152. map.each {println it}                          //it是一个关键字,代表map集合的每一个元素 
  153. 除了用于迭代之外,闭包可以单独定义: 
  154. def say={word-> println "Hi, $word!"
  155. 调用: 
  156.         say("groovy"
  157.         say.call("groovy & java"
  158. 输出: 
  159. Hi, groovy! 
  160. Hi, groovy & java! 
  161. 看起来,闭包类似于方法,需要定义参数和要执行的语句,它也可以通过名称被调用。然而闭包对象(不要奇怪,闭包也是对象)可以作为参数传递(比如前面的闭包作为参数传递给map的each方法)。而在java中,要做到这一点并容易(也许c++的函数指针可以,但不要忘记java中没有指针)。其次,闭包也可以不命名(作为代价,不能在定义闭包时执行一次),而方法不可以。 
  162. 12、类 
  163. Groovy类的java类一样,你完全可以用标准java bean的语法定义一个Groovy类。但作为另一种语言,我们可以使用更Groovy的方式定义的使用类,这样的好处是,你可以少写一半以上的javabean代码。 
  164. 1)不需public修饰符 
  165. 如前面所言,Groovy的默认访问修饰符就是public,如果你的Groovy类成员需要public修饰,则你根本不用写它。 
  166. 2)不需要类型说明 
  167. 同样前面也说过,Groovy也不关心变量和方法参数的具体类型。 
  168. 3)不需要getter/setter方法 
  169. 不要奇怪,在很多ide(如eclipse)早就可以为程序员自动产生getter/setter方法了。在Groovy中,则彻底不需要getter/setter方法--所有类成员(如果是默认的public)根本不用通过getter/setter方法引用它们(当然,如果你一定要通过getter/setter方法访问成员属性,Groovy也提供了它们)。 
  170. 4)不需要构造函数 
  171. 不再需要程序员声明任何构造函数,因为实际上只需要两个构造函数(1个不带参数的默认构造函数,1个只带一个map参数的构造函数--由于是map类型,通过这个参数你可以构造对象时任意初始化它的成员变量)。 
  172. 5)不需要return 
  173. Groovy中,方法不需要return来返回值吗?这个似乎很难理解,看后面的代码吧,因此,Groovy风格的类是这样的 
  174. 6)不需要() 
  175. Groovy中方法调用 可以省略()(构造函数除外),也就是说下面两名是等同的: 
  176.         def person1 = new Person() 
  177.         person1.setName "john" 
  178.         person1.setAge(25
  179. 下面看一个完整类定义的例子: 
  180. class Person { 
  181.     def name 
  182.     def age 
  183.     String toString() { //注意方法是String,因为我们需要覆盖的方法为String类型 
  184.         "$name, $age" 
  185.     } 
  186. 如果你使用javabean风格来做同样的事,起码代码量要增加1倍以上。 
  187. 我们可以使用默认构造方法实例化Person类: 
  188.         def person1 = new Person() 
  189.         person1.setName "john" 
  190.         person1.setAge(25
  191. 也可以用Groovy的风格做同样的事: 
  192. def person2=new Person(['name':'john','age':25])     
  193. println person2 
  194. 这样需要注意我们覆盖了Object的toString方法,因为我们想通过println person1这样的方法简单地打印对象的属性值。 
  195. 然而toString方法中并没有return一个String,但不用担心,Groovy默返回方法的最后一行的值。 
  196. 13、?运算符 
  197. 在java中,有时候为了避免出现空指针异常,我们通常需要这样的技巧: 
  198. if(rs!=null) { 
  199.             rs.next() 
  200.             ...... 
  201.         } 
  202. 在Groovy中,可以使用?操作符达到同样的目的: 
  203. rs?.next() 
  204. ?在这里是一个条件运算符,如果?前面的对象非null,执行后面的方法,否则什么也不做。 
  205. 14、可变参数 
  206. 等同于java5中的变长参数。首先我们定义一个变长参数的方法sum: 
  207.     int sum(int... var) { 
  208.         def total=0 
  209.         for(i in var) { 
  210.             total+=1 
  211.         } 
  212.             return total 
  213.     } 
  214. 我们可以调用sum时使用任意个的参数(1个,2个,3个……): 
  215.         println sum(1)       
  216.         println sum(1,2
  217.         println sum(1,2,3
  218. 15、枚举 
  219. 定义一个enum: 
  220.         def today=Day.SATURDAY 
  221.         switch(today) { 
  222.             //Saturday or Sunday 
  223.             case [Day.SATURDAY, Day.SUNDAY]: 
  224.             println "Weekends are cool" 
  225.             break
  226.             case Day.MONDAY..Day.FRIDAY: 
  227.             println "Boring work day" 
  228.             break
  229.             default
  230.             println "Are you sure this is a valid day?" 
  231.         } 
  232. 注意,switchcase中可以使用任何对象,尤其是可以在case中使用List和范围,从而使分支满足多个条件。 
  233. 同java5一样,Groovy支持带构造器。属性的方法的enum
  234.  
  235. enum Planet { 
  236.     MERCURY(3.303e+23,2.4397e6), 
  237.     VENUS(4.869e+24,6.0518e6), 
  238.     EARTH(5.976e+24,6.37814e6), 
  239.     MARS(6.421e+23,3.3972e6), 
  240.     JUPITER(1.9e+27,7.1492e7), 
  241.     SATURN(5.688e+26,6.0268e7), 
  242.     URANUS(8.686e+25,2.5559e7), 
  243.     NEPTUNE(1.024e+26,2.4746e7) 
  244.     double mass 
  245.     double radius 
  246.     Planet(double mass, double radius) { 
  247.         this.mass=mass 
  248.         this.radius=radius 
  249.     } 
  250.     void printMe(){ 
  251.         println :"${name()} has a mass of ${mass} and a radius of ${radius}" 
  252.     } 
  253. Planet.EARTH.printMe() 
  254. 16、Elvis运算符 
  255. 这是三目运算符“?:”的简单形式,三目运算符通常以这种形式初恋: 
  256. String displayName=name!=null?name:"Unknown"
  257. 在Groovy中,也可以简化为(因为null在Groovy中可以转化为布尔值false): 
  258. String displayName=name?name:"Unknown"
  259. 基于“不重复”的原则,可以是用elvis操作符再次简化为: 
  260. String displayName=name?:"Unknown"
  261. 17、动态性 
  262. Groovy所有的对象都有一个元素metaClass,我们可以通过metaClass属性访问该元类。通过元类,可以为这个对象增加方法(在java中不可想象!)见下面的代码,msg是一个String,通过元类,我们为msg增加了一个String类中没有的方法up: 
  263. def msg="Hello!" 
  264.         println msg 
  265.         println msg.metaClass  
  266.         String.metaClass.up={delegate.toUpperCase()} 
  267.         println msg.up() 
  268. 通过元类,我们还可以检索对象所拥有的方法和属性(就是反射): 
  269. msg.metaClass.metaMethods.each {println it.name} 
  270.         msg.metaClass.properties.each { println it.name} 
  271. 甚至我们可以看到我们刚才添加的up方法。 
  272. 我们可以通过元类判断有没有一个叫up的方法,然后再调用它: 
  273. if (msg.metaClass.respondsTo(msg, 'up')) { 
  274.             println msg.up() 
  275.         } 
  276. 当然,也可以推断它有没有一个叫bytes的属性: 
  277.         if(msg.metaClass.hasProperty(msg, 'bytes')) { 
  278.             println msg.bytes.encodeBase64() 
  279.         }