楼主: shiren1118

Java帝国的王储——Groovy !之学习

[复制链接]
论坛徽章:
7
开发板块每日发贴之星
日期:2007-08-16 01:07:19授权会员
日期:2007-09-05 19:24:16开发板块每日发贴之星
日期:2007-09-16 01:04:47ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44开发板块每日发贴之星
日期:2007-11-10 01:06:26开发板块每日发贴之星
日期:2007-11-24 01:02:58生肖徽章2007版:鸡
日期:2008-01-02 17:35:53
11#
 楼主| 发表于 2007-11-19 10:14 | 只看该作者
清单 2. 不要忘记 def 关键字!

class Person {
  @Property fname
  @Property lname
  @Property age
  @Property address
  @Property contactNumbers
  String toString(){
   
   numstr = new StringBuffer()
       
   if (contactNumbers != null){
           contactNumbers.each{
                numstr.append(it)
                numstr.append(" ")
           }
   }
   
   "first name: " + fname + " last name: " + lname +
        " age: " + age + " address: " + address +
        " contact numbers: " + numstr.toString()
}
}


认识这个代码吗?它借用来自“在 Java 应用程序中加一些 Groovy 进来 ”一文的清单 1 中的代码。在清单 3 中,可以看到运行代码时弹出的错误消息:

清单 3. 错误消息

c:devprojects>groovy BusinessObjects.groovy

BusinessObjects.groovy: 13: The variable numstr is undefined in the current scope
@ line 13, column 4.
      numstr = new StringBuffer()
      ^
1 Error


当然,解决方案也是在 toString 方法中将 def 关键字添加到 numstr。清单 4 显示了这个更合适的 def 解决方案。

清单 4. 用 def 重新处理

  String toString(){
   
   def numstr = new StringBuffer()
       
   if (contactNumbers != null){
           contactNumbers.each{
                numstr.append(it)
                numstr.append(" ")
           }
   }
   
   "first name: " + fname + " last name: " + lname +
        " age: " + age + " address: " + address +
        " contact numbers: " + numstr.toString()
}


另外,我还可以为 numstr 提供一个像 private 这样的修饰符,或者将它声明为 StringBuffer。不论哪种方法,重要的一点是:在 JSR Groovy 中,必须在变量前加上某些东西。

使用道具 举报

回复
论坛徽章:
7
开发板块每日发贴之星
日期:2007-08-16 01:07:19授权会员
日期:2007-09-05 19:24:16开发板块每日发贴之星
日期:2007-09-16 01:04:47ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44开发板块每日发贴之星
日期:2007-11-10 01:06:26开发板块每日发贴之星
日期:2007-11-24 01:02:58生肖徽章2007版:鸡
日期:2008-01-02 17:35:53
12#
 楼主| 发表于 2007-11-19 10:14 | 只看该作者
封闭闭包(closure)

闭包的语法发生了变化,但是大多数变化只与参数有关。在经典的 Groovy 中,如果为闭包声明参数,就必须用 | 字符作为分隔符。您可能知道,| 也是普通 Java 语言中的位操作符;结果,在 Groovy 中,只有在某个闭包的参数声明的上下文中,才能使用 | 字符。

在“alt.lang.jre: 感受 Groovy”的清单 21 中,我演示了迭代,查看了用于闭包的经典 Groovy 参数语法。可以回想一下,我在集合上运用了 find 方法,该方法试图找到值 3。然后我传入了参数 x,它代表 iterator 的下一个值 (有经验的 Groovy 开发人员会注意到,x 完全是可选的,我可以引用隐式变量 it)。使用 JSR Groovy 时,必须删除 | ,并用 Nice 样式的 -> 分隔符代替它,如清单 5 所示:

清单 5. 新的 Groovy 闭包语法

[2, 4, 6, 8, 3].find { x ->
  if (x == 3){
    println "found ${x}"
  }
}


新的闭包语法有没有让您想起 Nice 语言的块语法呢?如果不熟悉 Nice 语言,请参阅 alt.lang.jre: Nice 的双倍功能,这是我在 alt.lang.jre 系列上贡献的另一篇文章。

正如我在前面提到过的,Groovy 的 JDK 没有变。但是就像刚才所学到的,闭包却发生了变化;所以,使用 Groovy 的 JDK 中那些漂亮的 API 的方式也发生了变化,但仅仅是轻微的变化。在清单 6 中,可以看到这些变化对 Groovy IO 的影响根本是微不足道的:

清单 6. Groovy 的 JDK 依旧功能强大!

import java.io.File
new File("maven.xml").eachLine{ line ->
  println "read the following line -> " + line
}


改编过滤器

现在,不得不让您跳过很大一部分,但您还记得在“用 Groovy 进行 Ant 脚本编程”一文中,我是如何介绍闭包的威力和工具的吗?谢天谢地,我在这个专栏的示例中所做的多数工作都很容易针对新语法重新进行改编。在清单 7 中,我只是将 @Property 属性添加到 Filter 的成员 strategy(最初在那篇文章的清单 2 和清单 3 中显示)。然后在闭包中添加 -> 分隔符,万岁 —— 它可以工作了!

清单 7. 过滤改编!

package com.vanward.groovy
class Filter{
@Property strategy
boolean apply(str){
  return strategy.call(str)
}
}
simplefilter = { str ->
  if(str.indexOf("java.") >= 0){
    return true
  }else{
    return false
  }
}
               
fltr = new Filter(strategy:simplefilter)
assert !fltr.apply("test")
assert fltr.apply("java.lang.String")
               
rfilter = { istr ->
  if(istr =~ "com.vanward.*"){
    return true
  }else{
    return false
  }
}
               
rfltr = new Filter(strategy:rfilter)
assert !rfltr.apply("java.lang.String")
assert rfltr.apply("com.vanward.sedona.package")


目前为止还不坏,您觉得呢?新的 Groovy 语法很容易掌握!

使用道具 举报

回复
论坛徽章:
7
开发板块每日发贴之星
日期:2007-08-16 01:07:19授权会员
日期:2007-09-05 19:24:16开发板块每日发贴之星
日期:2007-09-16 01:04:47ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44开发板块每日发贴之星
日期:2007-11-10 01:06:26开发板块每日发贴之星
日期:2007-11-24 01:02:58生肖徽章2007版:鸡
日期:2008-01-02 17:35:53
13#
 楼主| 发表于 2007-11-19 10:15 | 只看该作者
对范围(range)的更改

Groovy 的范围语法的变化非常小。在经典的 Groovy 中,您可以通过使用 ... 语法指明排他性(即上界)来避开这些变化。在 JSR Groovy 中,只要去掉最后一个点(.),并用直观的 < 标识替代它即可。

请注意观察我在下面的清单 8 中对来自“Feeling Groovy”一文中的范围示例进行的改编:

清单 8. 新的范围语法

myRange = 29..<32
myInclusiveRange = 2..5
println myRange.size() // still prints 3
println myRange[0]   // still prints 29
println myRange.contains(32) //  still prints false
println myInclusiveRange.contains(5) // still prints true

使用道具 举报

回复
论坛徽章:
7
开发板块每日发贴之星
日期:2007-08-16 01:07:19授权会员
日期:2007-09-05 19:24:16开发板块每日发贴之星
日期:2007-09-16 01:04:47ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44开发板块每日发贴之星
日期:2007-11-10 01:06:26开发板块每日发贴之星
日期:2007-11-24 01:02:58生肖徽章2007版:鸡
日期:2008-01-02 17:35:53
14#
 楼主| 发表于 2007-11-19 10:15 | 只看该作者
您是说存在歧义?

您可能注意到,在使用 Groovy 时,有一项微妙的功能可以让您获得方法引用,并随意调用这个引用。可以将方法指针当作调用对象方法的方便机制。关于方法指针,有意思的事情是:它们的使用可能就表明代码违反了迪米特法则。

您可能会问“什么是迪米特法则”呢?迪米特法则使用只与直接朋友对话 这句格言指出:我们应当避免调用由另一个对象方法返回的对象上的方法。例如,如果 Foo 对象公开了一个 Bar 对象类型,那么客户应当通过 Foo 访问 Bar 的行为。结果可能是一些脆弱的代码,因为对某个对象的更改会传播到整个范围。

一位受尊敬的学者写了一篇优秀的文章,叫做“The Paperboy, the Wallet, and the Law of Demeter”(请参阅 参考资料)。这篇文章中的示例是用 Java 语言编写的;但是,我在下面用 Groovy 重新定义了这些示例。在清单 9 中,可以看到这些代码演示了迪米特法则 —— 如何用它洗劫人们的钱包!

使用道具 举报

回复
论坛徽章:
7
开发板块每日发贴之星
日期:2007-08-16 01:07:19授权会员
日期:2007-09-05 19:24:16开发板块每日发贴之星
日期:2007-09-16 01:04:47ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44开发板块每日发贴之星
日期:2007-11-10 01:06:26开发板块每日发贴之星
日期:2007-11-24 01:02:58生肖徽章2007版:鸡
日期:2008-01-02 17:35:53
15#
 楼主| 发表于 2007-11-19 10:19 | 只看该作者
一些新东西!

如果在 Groovy 的 JSR 发行版中没有什么新东西,那就没有意思了,不是吗?谢天谢地,JSR Groovy 引入了 as 关键字,它是一个方便的类型转换机制。这个特性与新的对象创建语法关系密切,新的语法可以用类似数组的语法很容易地在 Groovy 中创建非定制 类。所谓非定制,指的是在 JDK 中可以找到的类,例如 Color、Point、File,等等。

在清单 11 中,我用这个新语法创建了一些简单类型:

清单 11. Groovy 中的新语法

def nfile = ["c:/dev", "newfile.txt"] as File
def val = ["http", "www.vanwardtechnologies.com", "/"] as URL
def ival = ["89.90"] as BigDecimal
println ival as Float


注意,我用便捷语法创建了一个新 File 和 URL,还有 BigDecimal ,还要注意的是,我可以用 as 把 BigDecimal 类型转换成 Float 类型。




        回页首


接下来是什么呢?

JSR 对 Groovy 的规范化过程并没有结束,特别是在有些东西在 Groovy 的当前版本中(在本文发布时是 JSR-2)仍然不起作用的情况下。例如,在新的 Groovy 中,不能用 do/while 循环。此外,新的 Groovy 还无法完全支持 Java 5.0 的 for 循环概念。结果是,可以使用 in 语法,但是不能使用新推出的 : 语法。

这些都是重要的特性,不能没有,但是不用担心 —— Groovy 小组正在努力工作,争取在未来几个月内实现它们。请参阅 参考资料,下载最新的发行版本,并学习更多关于 JSR Groovy 进程的内容;还请继续关注下个月的“实战 Groovy”,下个月我(和两个客座专栏作家)将深入讨论 Groovy 闭包的更精彩的细节。

使用道具 举报

回复
论坛徽章:
7
开发板块每日发贴之星
日期:2007-08-16 01:07:19授权会员
日期:2007-09-05 19:24:16开发板块每日发贴之星
日期:2007-09-16 01:04:47ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44开发板块每日发贴之星
日期:2007-11-10 01:06:26开发板块每日发贴之星
日期:2007-11-24 01:02:58生肖徽章2007版:鸡
日期:2008-01-02 17:35:53
16#
 楼主| 发表于 2007-11-19 10:21 | 只看该作者
1、 hello world(看看开发环境) 2、 99乘法表(看看循环、格式化输出)3 做个比较复杂点的程序,看看过程调用、循环、判断这些基本的语言特征。



好些年没有学新语言了,还是先试试这三板过时的(面向对象、数据库、网络服务都没有涉及到)斧头还能不能砍得了东西吧。

1 hello world

脚本语言就是方便,一点上下文都没有,一个println就搞定了



2 99乘法表

1def i=0
2def j
3while(i<9){
4    i++
5    j=1
6    while(j<=i){
7        print(j+"*"+i+"="+(i*j)+"        ")
8        j++
9    }
10    println()
11}

脚本语言就是松散,分号加不加都可以。语法和数据类型好像都跟java差不多。



3 写个复杂一点的例子。前两天看《程序员法则》刚好看到提起了著名的八皇后问题,就写个八皇后吧:

1int q=8
2int[] i=new int[q]
3int count=0
4long t = System.currentTimeMillis();
5scan(0)
6println("totle results:"+count)
7println("totle time:"+(System.currentTimeMillis()-t));
8def scan(n){
9    if (n==q){
10        println(i.toList())
11        count++
12        return
13    }
14    i[n]=0
15    while(i[n]<q){
16        i[n] = i[n]+1
17        if (check(n))
18            scan(n+1)
19    }
20}
21def check(n){
22    if (n>0)
23        for (j in 0..<n)
24            if (i[j]==i[n] || i[j]-i[n]==j-n || i[j]-i[n]==n-j )
25                return false
26    return true
27}



呵呵,典型的面向过程,全局变量都弄出来了。运行一下还满快的

使用道具 举报

回复
论坛徽章:
7
开发板块每日发贴之星
日期:2007-08-16 01:07:19授权会员
日期:2007-09-05 19:24:16开发板块每日发贴之星
日期:2007-09-16 01:04:47ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44开发板块每日发贴之星
日期:2007-11-10 01:06:26开发板块每日发贴之星
日期:2007-11-24 01:02:58生肖徽章2007版:鸡
日期:2008-01-02 17:35:53
17#
 楼主| 发表于 2007-11-19 10:22 | 只看该作者
groovy 学习笔记2 IDE

groovy虽然没有自己的IDE,但是它可以依附在很多现有的开发环境如eclipse,intelli idea等。不过不巧我都不大用这些开发环境的。还好,找到了groovy的ultraedit语法文件 这样在ultraedit下面也可以高亮显示、编译和运行groovy了。



ultraedit甚至还提供了命令自动补全功能,不过默认使用的组合键是ctrl+space,恰好和输入法切换键冲突了。不过我们可以修改组合键:


Advanced - Configuration - Key Mapping


在commands里面找到AutoComplete(命令不是按字母排序的,按一下“A”键就自动找到啦),然后输入焦点转到 Press New Key框中,选择自己喜欢的组合键,比如 Alt+space,确认组合键出现在框里面后点一下Assign键,大功告成。


详细介绍见 http://groovy.codehaus.org/UltraEdit+Plugin


editplus也是我心爱的编辑器之一,还好不只我喜欢editplus和groovy,有个韩国网站也有同好:http://www.javaclue.org/index.jsp


看不懂:-P。不过也不用看懂,直接把他们写的groovy语法文件








http://www.javaclue.org/groovy/editor/editplus/groovy.acp



http://www.javaclue.org/groovy/editor/editplus/groovy.stx





下载下来,在editplus的参数选项--设置和语法里面添加groovy的语法和自动补全文件,现在editplus也支持groovy的高亮显示和自动补全了。





不过editplus的自动补全和ultraedit有写不同,是敲一个关键字,然后按空格的时候把相关的语法元素自动补进来。

使用道具 举报

回复
论坛徽章:
7
开发板块每日发贴之星
日期:2007-08-16 01:07:19授权会员
日期:2007-09-05 19:24:16开发板块每日发贴之星
日期:2007-09-16 01:04:47ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44开发板块每日发贴之星
日期:2007-11-10 01:06:26开发板块每日发贴之星
日期:2007-11-24 01:02:58生肖徽章2007版:鸡
日期:2008-01-02 17:35:53
18#
 楼主| 发表于 2007-11-19 10:25 | 只看该作者
一个面向对象的语言往往都是通过package把对象组织起来的,但是很奇怪居然没有找到groovy的package方面的资料,难道groovy不支持?那么我们怎么用groovy来设计负责一点的程序呢?还是做试验试试吧:

Dog.groovy:

1package com
2class Dog {
3    public def name;
4    def bark ()  {
5        println("barking")
6    }
7    def say ()  {
8        println("My name is "+name);
9    }
10}
11


嗯,一只会说一句话的狗,还回吠哦。

编译一下看看有没有错: groovyc Dog.groovy
嗯,没有错,而且在当前目录下生成了一个com目录,其中有Dog.class文件

再建一个类来引用这个类  trainDog.groovy:
1dog = new com.Dog(name:"Doggie");
2dog.bark();
3dog.say();
4



运行……失败了:

Caught: General error during class generation: No such class: com.Dog in constructor call for class: trainDog. At [1:7] D:groovymygroovycom        rainDog.groovy

一番努力之后,始终无法让 trainDog.groovy运行起来,但是反编译这两个groovy生成的class文件看起来又很正确。算了,用java来运行它吧(还好一开始就配置了editplus下面的调试环境,下面的命令由editplus自动生成,不用自己敲了)

D:jdk1.5.0injava.exe -classpath .;d:groovygroovy-1.0-jsr-01.jar;d:groovylibasm-1.5.2.jar trainDog

果然不错:

---------- java ----------
barking
My name is Doggie
Normal Termination
输出完成(耗时 0 秒)。


看来groovy虽然可以直接运行,却不能直接相互引用。进行复杂应用的时候还是要先编译好以便他们可以相互引用类文件。此外groovy编译器会自动为包创建对应的目录,所以所有的groovy不管分散到多少包里面都要在同一个目录(所有包的上一层)下面编译。

使用道具 举报

回复
论坛徽章:
0
19#
发表于 2008-1-3 14:24 | 只看该作者
我觉得关键是思想,语言并不重要

使用道具 举报

回复
论坛徽章:
1
2008新春纪念徽章
日期:2008-02-13 12:43:03
20#
发表于 2008-1-4 15:51 | 只看该作者
关注一下

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表