二. 工具

1. 控制台

groovyConsole:

Groovy 控制台是一个非常易于使用和简单的轻量级的编辑器。你可以在里面做很多事情。

在编辑器里面可以书写代码,Windows 下,按下Ctrl + R 来运行代码,清除工作台的输出信息使用Ctrl + W 快捷键。

2. 编译

groovyc:

可以借助 Java 7 的动态调用设计的优势,可以使用--indy 标识符。这个在 Groovy 命令行下也同样适用。

动态调用可以帮助编译器提高性能,例如鸭子类型,元编程,方法缺失调用等。

3. Shell

groovysh:

在不需要交互的 shell 命令行下可以使用 groovysh 来执行 Groovy 代码。

4. 文档

groovydoc:

使用此命令可以从代码中生成文档。Groovy 里的代码的注释与 Java 是一样一样的。

/** This is a documentation comment. */
/* This is not */
// This is a one-line comment.

三. GDK

GDK(Groovy Development Kit ) 提供了很多适用和方便的方法,操作符,实用类还有其他的一些帮助类。

有些方法可以用在任何 Java 类中,例如each, 还有更多。

1. 集合

Groovy 提供了很多方便快捷的方法来操作集合。

  • sort —— 为集合排序
  • findAll —— 根据匹配的闭包条件,查找所有的元素
  • collect —— 一个遍历器,用来生成一个新的集合
  • inject —— 遍历循环所有元素,但最后返回一个值
  • each —— 根据给定的闭包条件遍历循环所有元素
  • eachWithIndex —— 根据值和对应的索引来遍历循环所有的元素
  • findIndexOf —— 根据核定的闭包条件返回第一个匹配的元素的索引
  • any—— 如果匹配了闭包条件则返回 true
  • every —— 如果匹配了闭包条件则返回 true
  • first —— 获取 List 的第一个元素
  • last —— 获取 List 的最后一个元素
  • tail —— 返回 List 里面除了第一个元素意外剩下所有的元素

2.“*”操作符

“*”操作符可以用来访问集合里面所有元素的属性。在很多情况下,可以与collect 方法替换使用。

例如你想打印在变量名为dragons的集合里面每个对象的 name 的值,可以使用

dragons*.name.each { println it }
3. GPath

在 GPath 里面, GPath很多地方类似于XPath。List 和 Map 都支持属性标记,Groovy 提供了语法糖来非常容易地处理集合。请看下面的代码:

def  listOfMaps = [['a': 11, 'b': 12], ['a': 21, 'b': 22]]
assert listOfMaps.a == [11, 21] //GPath notation
assert listOfMaps*.a == [11, 21] //spread dot notation listOfMaps = [['a': 11, 'b': 12], ['a': 21, 'b': 22], null]
assert listOfMaps*.a == [11, 21, null] // caters for null values
assert listOfMaps*.a == listOfMaps.collect { it?.a } //equivalent notation
// But this will only collect non-null values
assert listOfMaps.a == [11,21]

4. IO

GDK 对 IO操作做了很多工作。

(1).Files

GDK 增加了很多方法用来非常便利地进行读写。

println path.toFile().text

在File 类中增加了 getText() 方法,非常简洁地读取整个文件。

new  File("books.txt").text = "Modern Java"

使用 File 类中新增的setText() 方法,用来对文件进行写操作。关于二进制文件,可以使用bytes属性。

 byte[] data = new File('data').bytes
new File('out').bytes = data

如果你用InputStream 和 Reader 读取类,或者使用OutputStream 和Writer 写入类,还有如下方法:

new File('dragons.txt').withInputStream {in -> }
new File('dragons.txt').withReader {r -> }
new File('dragons.txt').withOutputStream {out ->}
new File('dragons.txt').withWriter {w -> }

最后,你可以使用eachLine 方法来读取文件的一行,例如:

new  File('dragons.txt').eachLine { line->
println "$line"
}
//OR
new File('dragons.txt').eachLine { line, num ->
println "Line $num: $line"
}

在所有的情况中,即使出现异常,Grovvy 都能关闭 IO资源。

(2). URLs

GDK 提供了一个超级简单的方式来访问 URL。

下面的例子,是用 Java 代码来打开 Http 连接,从谷歌地址上读取数据并存放在 btye 数组中,然后打印所有的内容:

URL url = new  URL("http://google.com");
InputStream input = (InputStream) url.getContent();
ByteArrayOutputStream out = new ByteArrayOutputStream();
int n = 0;
byte[] arr = new byte[1024]; while (-1 != (n = input.read(arr)))
out.write(arr, 0, n); System.out.println(new String(out.toByteArray()));

然而,上面的代码用 Groovy 一句话就能搞定!!

println "http://google.com".toURL().text
(3.)Range

Range是 Groovy 内置类型。它可以被用在循环,switch 语句,抽取子字符串等。Range 的语法为start .. end

Range 用在each 方法和循环中非常便利:

(1..4).each {print it} //1234
for (i in 1..4) print i //1234

在 switch 语句中:

case  12..30: // Range  12  to  30

Tip

在 switch 语句中 Range 里的数据类型必须一致。

你还可以使用 Range 的 getAt方法从字符串中截取子字符串:

def  text = 'learning groovy'
println text[0..4] //learn
println text[0..4,8..-1] //learn groovy

Tip

-1表示集合或是字符串里最后一个元素。

你甚至可以在集合中使用 Range。

def list = ['hank', 'john', 'fred']
println list[0..1] //[hank, john]

你可以使用 “..<” 操作符定义 Range 的最后元素的开区间。

 (1..<5).each {print it} //1234
(4.) 实用工具类

ConfigSlurper实用类用来读取配置信息,它是一种 Groovy 脚本。像 Java 中的*.properties的文件,可以使用“.”导航符进行访问,它也可以应用在闭包的配置的值和任何对象类型中。

def config = new ConfigSlurper().parse('''
app.date = new Date()
app.age = 42
app {
name = "Test${42}"
}
''') def properties = config.toProperties() assert properties."app.date" instanceof String
assert properties."app.age" == '42'
assert properties."app.name" == 'Test42'

Expando工具类用来创建动态扩展对象。你可以为对象添加属性和方法,在动态元编程中此类非常实用。例如:

def expando = new  Expando()
expando.name = { -> 'Draco' }
expando.say = { String s -> "${expando.name} says: ${s}" }
expando.say('hello') // Draco says: hello

ObservableList/Map/Set

Groovy 提供了可供观察的 List,Map和 Set。当这些集合在新增,删除,修改元素时会触发PropertyChangeEvent( java.beans package)事件。需要注意的是,这个事件不仅会触发,它还持有属性的名字以及属性的新旧值。

例如,下面的例子使用ObservableList来打印所有触发的事件类。

def  list = new  ObservableList()
def printer = {e -> println e.class}
list.addPropertyChangeListener(printer)
list.add 'Harry Potter'
list.add 'Hermione Granger'
list.remove(0)
println list // 打印结果为:
class groovy.util.ObservableList$ElementAddedEvent
class java.beans.PropertyChangeEvent
class groovy.util.ObservableList$ElementAddedEvent
class java.beans.PropertyChangeEvent
class groovy.util.ObservableList$ElementRemovedEvent
class java.beans.PropertyChangeEvent
[Hermione Granger]

四. 源于 Java

1. 静态方法默认值

Groovy 为方法参数提供了默认值,例如,下面的代码fly 方法有个名为 text 的参数

def fly(String text = "flying") {println text}

从 Java 的角度来看这需要创建两个重载的方法:

def  fly() {println "flying"}
def fly(String text) {println text}

这个方法只要不与现存的方法冲突,可以设置任意长度的参数。

2. Equals, Hashcode , 更多方法

在 Java 中一项比较繁琐的操作就是提供 equal,hashcode 等方法。为了解决这个问题,Groovy 提供了 @EqualsAndHashCode 注解。只要放在类定义的上面,万事大吉了!

除此之外,我们通常根据属性来创建不同的构造方法,为此,Groovy 提供了 @TupleConstructor 注解。此注解非常容易第根据你属性的定义来定义构造方法。注意,此注解要放在定义类关键字 class 的前面。

当然,还有 @ToString 注解,用在放在 toString() 上。

当然,如果你想实现上面所有的功能,只需要一个 @Canonical 注解就全部搞定。

import   groovy.transform.*
@Canonical class Dragon {def name}
println new Dragon("Smaug")
// prints: Dragon(Smaug)
assert new Dragon("").equals(new Dragon(""))

3. 正则表达式

在 Groovy 中使用了非常简单的方式来匹配正则表达式。在 Java 中你必须使用 java.util.regex.Pattern 类,在 Groovy 中只是一行就能搞定。

按照规范你必须使用斜杠来包围正则表达式。这样才允许你使用一些特殊的正则语法,从而免去了使用两个反斜线的痛苦写法。例如:

def  isEmail = email ==∼ /[\w.]+@[\w.]+/

它相当于如下的 Java 代码:

Pattern patt = Pattern.compile("[\\w.]+@[\\w.]+");
boolean isEmail = patt.matches(email);

还可以只用操作符创建一个新的 Matcher类:

def email = 'mailto:adam@email.com'
def mr = email =∼ /[\w.]+@[\w.]+/
if (mr.find()) println mr.group()

这允许你在字符串内部使用正则表达式,并且从一个表达式中得到一个子组。

4. 缺失的Java语法

由于Groovy的独特的语法以及多年来Java一直增加新的东西,所以看起来Groovy缺失了一些功能。然而,我们可以通过其他方式来做这些相同的功能。例如,对于数组,对于 Groovy 来说是一个很困难的问题,因为Java创建数组的语法,数组里的值不会被编译,例如,下面的代码在Groovy里是报错的:

String[] array = new  String[] {"foo", "bar"};

而应该使用这样的语法:

String[] array = ['foo', 'bar'].toArray()

还有,在很长时间内 for (Type item : list) 这种循环是不支持的。但是你有两种替代方案,一是使用 “in” 关键字;二 是使用 each 方法。

// for (def item : list)
for (item in list) doStuff(item)
list.each { item -> doStuff(item) }

5. 语句末尾“;”可选

如果你以前用过 Java 的话,在 Groovy 中因为分号是可选的,可能会引起语句结束的疑惑问题。通常这不是问题,但是在一行中调用多个方法的话,可能会产生问题。这种情况下,你需要在每行代码结束后使用非结束的操作符,例如“.”, 看例子:

 class  Pie  {
def bake() { this }
def make() { this }
def eat() { this }
}
def pie = new Pie().
make().
bake().
eat()

如果你使用典型的Java语法的话,在Groovy里会引起编译错误:

def pie = new Pie() //Groovy interprets end of line
.make() // huh? what is this?

6. 泛型去哪里了?

Groovy 默认支持泛型,但并不是强制的。出于此原因,你可能在

Groovy 中很少会看到泛型的使用,例如,下面的代码在 Groovy 中是没有问题的。

 List<Integer> nums = [1, 2, 3.1415, 'pie']

但是,如果想在 Groovy 中强制使用泛型的话,需要在类或方法前加上对应的注解 @CompileStatic 或 @TypeChecked。例如:

import   groovy.transform.*
@CompileStatic
class Foo {
List<Integer> nums = [1, 2, 3.1415] //error
}

这样,就会引起编译错误:Incompatible generic argument types. Cannot assign java.util.List <java.lang.Number> to: java.util.List 。因为3.1415中Groovy里是 BigDecimal 类型的,而 List 要求泛型的类型为 Number 类型。

7. Groovy 的数字

这里涉及的是十进制数字,在 Groovy 里默认为 BigDecimal 类型的。这样,你在做数学运算时省去了四舍五入的问题。

如果你想使用 float 和 double 类型,只需要在数字后面加上 f 或 d 就可以了。

def  pie = 3.141592d

8. Boolean的解决方案

因为 Groovy 只是跟 Java 很相像,但并不是 Java,所有有时候会有些疑惑。其中一个就是 Boolean 的问题。

在 Boolean 的使用上,Groovy 更加自由。例如,下面的代码都可以表示 Boolean 类型为 true 的情况。

if ("foo") println("true")
if (!"") println("true")
if (42) println("true")
if (! 0) println("true")

9. Map的语法

Groovy 的语法糖可以直接在 Map 中使用字符串作为 key,这通常用起来非常方便。但是如果使用 Groovy 的属性访问语法糖时,但

Map中 元素的 key 是一个对象类型时,会导致迷惑不清。所以你需要直接使用 getClass() 方法。

除此而外,如果你使用变量作为 key 的话,也会出现类似的问题。这时你需要用括号把 key 括起来。例如:

1   def  foo = 1
2 def bar = 2
3 def map = [(foo): bar]

如果变量 foo 不括起来的的话,就会变成了foo这个字符串,而不是数字1了。

Groovy 学习手册(2)的更多相关文章

  1. Groovy 学习手册(7)

    10. Groovy GPars GPars 一开始在 Groovy 中作为一个单独的项目,同时带来了很多并发的机制.它包含了很多并行的map/redue,Actors,以及其他很多并发的模块. 1. ...

  2. Groovy 学习手册(6)

    9. 不可变特性 不可变特性和函数式编程在一起就像是花生酱和果酱在一起一样.虽然没有必要非要在一起使用,但他们相处得很好. 在纯正的函数式语言中,每个函数对本身之外没有影响,即没有副作用.这意味着每次 ...

  3. Groovy 学习手册(5)

    8. 函数式编程 函数式编程(FP)是一种编程风格,侧重于函数和最小化状态的变化(使用不可变的数据结构).它更接近于用数学来表达解决方案,而不是循序渐进的操作. 在函数式编程里,其功能应该是" ...

  4. Groovy 学习手册(4)

    6. 领域特定语言 Groovy 有许多特性,使它非常适合写DSL(领域特定语言).这些特性包活: 具有委托机制的闭包: 点号(.)和语句末尾的分号(;)是可选的: 运算符的重载(例如,加号,减号等) ...

  5. Groovy 学习手册(3)

    五. Groovy 的设计模式 设计模式是一种非常好的方式,可以使你的代码变得实用,可读又具有扩展性.跟 Java 相比,在 Groovy 里使用设计模式使代码更加简洁和容易. 1. 策略模式 设想一 ...

  6. Groovy 学习手册(1)

    1. 需要安装的软件 Java / Groovy 对应 Java 和 Groovy,你需要安装以下软件: Java JDK,例如 JDK 8 IDE,例如 Eclipse,NetBeans 8 Gro ...

  7. Kotlin强化实战!这份学习手册让你的面试稳如泰山

    一.引言 正如官网的slogan所描述:kotlin,是一门让程序员写代码时更有幸福的现代语言. 同时,也正如维基百科里介绍: JetBrains公司希望Kotlin能够推动IntelliJ IDEA ...

  8. Redis学习手册(目录)

    为什么自己当初要选择Redis作为数据存储解决方案中的一员呢?现在能想到的原因主要有三.其一,Redis不仅性能高效,而且完全免费.其二,是基于C/C++开发的服务器,这里应该有一定的感情因素吧.最后 ...

  9. git学习手册

    #git学习手册 git: Git是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理.[2] Git 是 Linus Torvalds 为了帮助管理 Linux内核开发而 ...

随机推荐

  1. iOS9中找不到XXX.dylib 与 is unavailable no availabel on ios (app extension) - use view controller 的解决办法

    在 iOS9 中现在找不到 XXX.dylib 了,比如libz.tbd  如果要用到 libz.dylib,可以用下面的办法,来自 Stack Overflow. Go to Build Phase ...

  2. JavaScript 之 最佳位置选择

    Javascript 文件(下面简称脚本文件)需要被HTML文件引用才能在浏览器中运行.在HTML文件中可以通过不同的方式来引用脚本文件,我们需要关注的是,这些方式的具体实现和这些方式可能会带来的性能 ...

  3. LCD显示——点阵字体

    Bitmap font 点阵字体是把每一个字符都分成16×16或24×24个点,然后用每个点的虚实来表示字符的轮廓. 点阵字体优点是显示速度快,不像矢量字体需要计算:其最大的缺点是不能放大,一旦放大后 ...

  4. bat脚本禁用和开启本地连接

    netsh interface set interface name="本地连接" admin=disabled //禁用本地连接 netsh interface set inte ...

  5. SQL Server时间戳

    select replace(replace(replace(replace(convert(varchar ,getdate() ,126) ,'-' ,'') ,' ' ,'') ,':' ,'' ...

  6. Linux下利用signal函数处理ctrl+c等信号

    前言 linux下能够通过信号机制来实现程序的软中断,是一个很实用的编程方法. 我们平时在程序执行的时候按下ctrl-c.ctrl-z或者kill一个进程的时候事实上都等效于向这个进程发送了一个特定信 ...

  7. rotate-list 旋转部分链表

    Given a list, rotate the list to the right by k places, where k is non-negative. For example:Given1- ...

  8. [转发]如何在ASP.NET的web.config配置文件中添加MIME类型

    常常有一些特殊的MIME类型是IIS中没有的,一般来说要我们自己手动添加.如果网站经常更换服务器或者网站代码是提供给多个用户使用,那么会造成网站中用到的特殊的MIME类型要经常性的在IIS上配置.这里 ...

  9. python模块之HTMLParser(原理很大程度上就是对类构造的熟练运用)

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python模块之HTMLParser(原理很大程度上就是对类构造的熟练运用) import HTMLPar ...

  10. 修改windows默认的远程连接端口

    打开注册表,找到以下路径项,并修改为你想要的端口,重启服务器即可. HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Serve ...