Groovy 入门
在这一节中,将真正开始进行 Groovy 编程。首先,学习如何轻松地安装 Groovy(通过 Eclipse Groovy 插件),然后从一些有助于了解 Groovy 的简单示例开始。
轻松安装 Groovy
为了迅速开始使用 Groovy,需要做的全部工作就是安装 Eclipse 的 Groovy 插件。打开 Ecliplse,在 Help 菜单中选择 Software Updates > Find and Install...。
图 1 显示了执行以上步骤之后出现的对话框:
图 1. Eclipse Feature Updates 对话框
在选项中导航
接下来,出现一个对话框,里面包含两个选项。请选择 Search for new features to install 单选按钮。单击 Next 按钮,然后选择 New Remote Site...。出现一个新的对话框,里面包含两个需要填写的字段:新位置的名称和该位置的 URL,如图 2 所示:
图 2. 确保为新的远程站点提供了正确的 URL
输入 “Groovy plugin” 作为名称,输入 “http://dist.codehaus.org/groovy/distributions/update/” 作为位置,单击 OK 按钮,在随后出现的 Sites to include in search 框中确保选中了名为 “Groovy plugin” 的项目 — 现在的列表应该如图 3 所示。
图 3.Eclipse 中的远程网站清单
完成安装
单击 Finish 按钮之后,应该会出现 Search Results 对话框。请再次确定选中了 “Groovy plugin” 框并单击 Next 按钮,这一步骤如图 4 所示:
图 4. 选择 Groovy 插件
经过一系列确认之后,将会下载插件,然后可能需要重新启动 Eclipse。
创建 Groovy 项目
Eclipse 重启之后,就能够创建第一个 Groovy 项目了。请确保创建两个源文件夹 — 一个称为 “groovy”,另一个称为 “java”。编写的 Groovy 代码放在 groovy 文件夹,Java 代码放在 java 文件夹。我发现将二者分开将会很有用,如图 5 所示:
图 5. 两个源文件夹 — Java 和 Groovy
将 Groovy 导入项目
项目创建之后,右键单击项目的图标,应该会看到一个Groovy
选项,如图 6 所示。请选择该选项,然后选择 Add Groovy Nature
选项。这样做可以将必要的 Groovy 库、编译器和运行程序导入到项目中。
图 6. 在 Eclipse 中添加 Groovy 特性
创建 Groovy 类
创建 Groovy 类很简单。选择 groovy 文件夹并右键单击它。选择 New,然后选择 Other,如图 7 所示:
图 7. 通过 New 菜单创建 Groovy 类
给类命名
在这里,找到 Groovy 文件夹,并选择 Groovy Class— 应该会看到一个对话框,如图 8 所示。
图 8.选择创建 Groovy 类
单击 Next
按钮,系统将要求您提供类的名称。输入 HelloWorld。
现在可以将 HelloWorld Groovy 类保留在默认包内,如图 9 所示。
图 9. 现在不必考虑包的问题!
虽然步骤看起来很多,但这与创建标准的 Java 类并没有什么区别。
Hello World! — 用 Groovy 编写的 Java 程序
单击 Finish 按钮,应该会看到如下所示的代码段:
class HelloWorld {
static void main(args) {
}
}
这看起来同前面的 Java HelloWorld 示例惊人地相似。但是请注意,它不包含 public 修改符。而且,如果仔细查看 main 方法的参数,会注意到它没有类型。
编译程序
现在在 main 方法内加入 println "Hello World",完成后的代码看起来如下所示:
class HelloWorld {
static void main(args) {
println "Hello World"
}
}
在源代码编辑器中应该能够右键单击,并选择 Compile Groovy File 选项,如图 10 所示。
图 10. 右键单击 Groovy 文件即可进行编译
运行程序
接下来,再次右键单击文件,选择 Run As 选项,然后选择 Groovy 选项。在 Eclipse 控制台中应该会看到输出的 “Hello World”,如图 11 所示。
图 11. 输出的 Hello World
学到了什么?
OK,那么这是一种突出重点的取巧方式。Groovy 实际上就是 Java。其语法不同 — 多数情况下会短一些 — 但 Groovy 代码 100% 符合 Java 字节码标准。下一节将进一步介绍这两种语言的交叉。
Groovy 变身为 Java
前面已经看到 Groovy 与 Java 代码实际上可以互换的第一个证据。这一节将进一步证明这点,继续使用 Groovy 构建的 HelloWorld 类。
Hello, Java!
为了使您确信 Groovy 就是 Java,现在在 HelloWorld 类声明和方法声明前面加上 public 修改符,如下所示:
public class HelloWorld {
public static void main(args) {
println "Hello World"
}
}
还不确信?
这个代码运行起来同前面的代码完全一样。但是,如果仍不确信,还可以在 args 参数前加上 String[]:
public class HelloWorld {
public static void main(String[]args) {
println "Hello World"
}
}
现在还没完 现在,还可以将 println 替换为 System.out.println— 而且不要忘记加上括号。
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World")
}
}
现在的代码与前面用 Java 编写的 Hello World 示例完全相同,但是哪个示例更容易编写呢?
请注意,原来的基于 Groovy 的 HelloWorld 类没有任何 public 修改符,没有任何类型(没有 String[]),而且提供了没有括号的 println 快捷方式。
Hello, Groovy!
如果喜欢,可以将这个过程完全翻转过来,回到基于 Java 的 Hello World 示例,删除文件里的所有内容,只保留 System.out 行,然后在这行删除 System.out 和括号。最后只剩下:
println "Hello World"
现在,哪个程序更容易编写呢?
运行程序!
Groovy 代码完全符合 Java 字节码标准,这个练习证明了这一点。在 Eclipse 中,选择Run
菜单选项Open Run Dialog...
。选择一个新的Java Application
配置。确保项目是您的 Groovy 项目。对于 Main 类,单击Search
按钮,找到 HelloWorld 类。请注意,单词 class 表明 Eclipse Groovy 插件已经将 .groovy 文件编译为 .class 文件。
在图 12 中可以看到整个这个过程 — 如果以前在 Eclipse 中运行过 Java 类,那么您应该对这个过程很熟悉。
图 12. Groovy 代码完全符合 Java 字节码标准
单击 Run
按钮,看到什么了?实际上,“Hello World!” 从未像现在这样能够说明问题。
Groovy 是没有类型的 Java 代码
很可能将 Groovy 当成是没有规则的 Java 代码。但实际上,Groovy 只是规则少一些。这一节的重点是使用 Groovy 编写 Java 应用程序时可以不用考虑的一个 Java 编程的具体方面:类型定义。
为什么要有类型定义?
在 Java 中,如果要声明一个 String 变量,则必须输入:
String value = "Hello World";
但是,如果仔细想想,就会看出,等号右侧的字符已经表明 value 的类型是 String。所以,Groovy 允许省略 value 前面的 String 类型变量,并用 def 代替。
def value = "Hello World"
实际上,Groovy 会根据对象的值来判断它的类型。
运行程序!
将 HelloWorld.groovy 文件中的代码编辑成下面这样:
String message = "Hello World"
println message
运行这段代码,应该会在控制台上看到与前面一样的 “Hello World”。现在,将变量类型 String 替换为 def 并重新运行代码。是不是注意到了相同的结果?
除了输出 message 的值,还可以用以下调用输出它的类型:
def message = "Hello World"
println message.class
输出 “class java.lang.String” 应该是目前为止很受欢迎的一项变化!如果想知道到底发生了什么,那么可以告诉您:Groovy 推断出 message 一定是 String 类型的,因为它的值是用双引号括起来的。
类型推断的更多内容
您可能听说过,在 Groovy 中 “一切都是对象” — 但对于类型来说这句话意味着什么呢?让我们看看如果将前面示例中的 String 替换为数字会怎么样,如下所示:
def message = 12
println message.class
message 变量的数字值看起来像是 Java 的原生类型 int。但是,运行这个代码就可以看出,Groovy 将它作为 Integer。这是因为在 Groovy 中 “一切都是对象”。
Java 中的所有对象都扩展自 java.lang.Object,这对 Groovy 来说非常方便。即使在最糟的情况下,Groovy 运行时不能确定变量的类型,它只需将变量当成 Object,问题就解决了。
继续使用这段代码。将 message 改成自己喜欢的任意类型:Groovy 会在运行时尽其所能推断出这个变量的类型。
无类型有什么意义
那么,Groovy 缺少类型意味着所需的输入更少。不可否认,将 String 替换成 def 并没有真正节约多少打字工作 — 三个字母并不值得如何夸耀!但是在更高的层次上看,在编写大量不仅仅包含变量声明的代码的时候,没有类型确实减少了许多打字工作。更重要的是,这意味着要阅读的代码要少得多。最后,Groovy 缺少类型能够带来更高的灵活性 — 不需要接口或抽象类。
所以,只需要使用 def 关键字就能在方法中声明一个独立变量,不需要将 def 关键字作为方法声明中的参数。在 for 循环声明中也不需要它,这意味着不用编写 (int x = 0; x < 5; x++),相反,可以省略 int,保留空白。
通过 Groovy 进行循环
同大多数脚本语言一样,Groovy 经常被宣传为生产力更高 的 Java 语言替代品。您已经看到了 Groovy 缺少类型能够如何减少打字工作。在这一节,将创建并试用一个 repeat 函数。在这个过程中,将进一步探索 Groovy 提高效率的方式。
更好、更短的循环
下面这种方法可以更好地感受 Groovy 缺乏类型的好处:首先,用与创建 HelloWorld 相同的方式创建一个 Groovy 类,将这个类称为 MethodMadness,并删除自动生成的类体:将要定义一个独立的 repeat 函数。现在在控制台中输入以下代码:
def repeat(val){
for(i = 0; i < 5; i++){
println val
}
}
起初,从 Java 的角度来看,这个小函数看起来可能有些怪(实际上,它很像 JavaScript)。但它就是 Java 代码,只不过是用 Groovy 的样式编写的。
深入方法
repeat 函数接受一个变量 val。请注意参数不需要 def。方法体本质上就是一个 for 循环。
调用这个函数。
repeat("hello world")
会输出 “hello world” 五次。请注意,for 循环中省略了 int。没有变量类型的 for 循环要比标准的 Java 代码短些。现在看看如果在代码里加入范围会出现什么情况。
Groovy 中的范围
范围 是一系列的值。例如 “0..4” 表明包含 整数 0、1、2、3、4。Groovy 还支持排除范围,“0..<4” 表示 0、1、2、3。还可以创建字符范围:“a..e” 相当于 a、b、c、d、e。“a..<e” 包括小于 e 的所有值。
循环范围
范围为循环带来了很大的方便。例如,前面从 0 递增到 4 的 for 循环如下所示:
for(i = 0; i < 5; i++)
范围可以将这个 for 循环变得更简洁,更易阅读:
def repeat(val){
for(i in 0..5){
println val
}
}
设置范围 如果运行这个示例,可能会注意到一个小问题:“Hello World” 输出了六次而不是五次。这个问题有三种解决方法:
将包含的范围限制到 4:
for(i in 0..4)
从 1 而不是 0 开始:
def repeat(val){
for(i in 1..5){
println val
}
}
将范围由包含改为排除:
def repeat(val){
for(i in 0..<5){
println val
}
}
不论采用哪种方法,都会得到原来的效果 — 输出 “Hello World” 五次。
默认参数值
现在已经成功地使用 Groovy 的范围表达式缩短了 repeat 函数。但这个函数依然有些限制。如果想重复 “Hello World” 八次该怎么办?如果想对不同的值重复不同次数 — 比如 “Hello World” 重复八次,“Goodbye Sunshine” 重复两次,这时该怎么办?
每次调用 repeat 时都要指定需要的重复次数的做法已经过时了,特别是在已经适应了默认行为(重复五次)的时候。
Groovy 支持默认参数值,可以在函数或方法的正式定义中指定参数的默认值。调用函数的程序可以选择省略参数,使用默认值。
更加复杂的参数值
使用前面的 repeat 函数时,如果希望调用程序能够指定重复值,可以像下面这样编码:
def repeat(val, repeat=5){
for(i in 0..<repeat){
println val
}
}
像下面这样调用该函数:
repeat("Hello World", 2)
repeat("Goodbye sunshine", 4)
repeat("foo")
结果会输出 “Hello World” 两次,“Goodbye sunshine” 四次,“foo” 五次(默认次数)。