Chinaunix首页 | 论坛 | 博客
  • 博客访问: 30465653
  • 博文数量: 708
  • 博客积分: 12163
  • 博客等级: 上将
  • 技术积分: 8240
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-04 20:59
文章分类

全部博文(708)

分类: Java

2009-06-05 14:55:08

1、类

1)类

l         Groovy的类定义和Java类似

Ø         方法可以基于类(static)或实例

Ø         可以为publicprotectedprivate

Ø         支持常用的Java修饰符,如synchronized

l         Groovy的不同地方:缺省是public

l         Groovy支持JavaBean机制:GroovyBean

l         每个Groovy类都是字节码/JVM级的Java类,任何方法对Java都是有效的,反之亦然

l         你可以指定方法的参数类型和返回类型,这样可以在通常的Java代码中更好的工作

l         你可以用上面的方式来实现接口或重载方法

l         如果省略方法的类型,就会使用缺省的java.lang.Object

2)脚本

l         Groovy支持纯脚本,而不需要声明类,如Foo.groovy包含下面的脚本:

println "Nice cheese Gromit!"

l         运行脚本的过程:

Ø         编译成Foo.class(还会有一些内类),该类扩展groovy.lang.Script

Ø         执行自动生成的main方法

Ø         实例化Foo

Ø         调用run方法执行脚本内容

l         可以在Java代码中执行脚本,同时还可以传递变量值到脚本中

l         Foo.groovy内容修改如下

println "Nice ${cheese} Gromit!"

l         下面是执行脚本的UseFoo

import groovy.lang.Binding;
import groovy.lang.Script;
 
public class UseFoo {
       public static void main(String[] args) {
              Binding binding = new Binding();
              binding.setVariable("cheese", "Cheddar");
         
              Script foo = new Foo(binding);
              foo.run();
       }
}

l         UseFoo运行的结果是:Nice Cheddar Gromit!

l         执行脚本的方法是创建Foo类实例,调用其run方法

l         Foo类有一个带Binding参数的构造函数,可以通过Binding类的setVariable方法设置值给脚本中的属性变量

l         Foo类有一个不带参数的构造函数,在不传递属性变量值时使用

l         在脚本结束后,脚本中创建的任何变量都会在Binding中,以供在Java中访问

l         再将Foo.groovy内容修改如下

println "Nice ${cheese} Gromit!"
cheese = "changed"

l         UseFoo类修改为:

import groovy.lang.Binding;
import groovy.lang.Script;
 
public class UseFoo {
       public static void main(String[] args) {
              Binding binding = new Binding();
              binding.setVariable("cheese", "Cheddar");
         
              Script foo = new Foo(binding);
              foo.run();
              println binding.getVariable("cheese");
       }
}

l         UseFoo运行的结果是:

Nice Cheddar Gromit!
changed

3)脚本中的函数

l         不同于基于ClassGroovy,纯脚本中的函数用def关键字声明

def foo(list, value) {
    println "Calling function foo() with param ${value}"
    list << value
}
 
x = []
foo(x, 1)
foo(x, 2)
assert x == [1, 2]
 
println "Creating list ${x}"

2、闭包

1)概述

l         闭包是一种传递执行代码块的强大方法。

l         可以把闭包看作Java中的匿名内类,但是只有单一的(匿名)方法。

l         闭包可以被用作循环的一种替代方法

[1, 2, 3, 4].each { println(it) }

l         使用闭包可以使异常处理和关闭资源变得更简单,具体例子请参看Groovy SQL

2)比较闭包和匿名内类

l         不同于Java匿名内类,Groovy 支持“true closures”:状态可以被传递到闭包外部

l         局部变量在闭包创建时可以被使用和修改;闭包中创建的任何变量可以作为局部变量,对外部可见

l         看下面的例子:

count = 0
last = 0
[1, 2, 3, 4].each { count += it; last = it } 
println("the sum is ${count} and the last item was ${last}")

输出结果:the sum is 10 and the last item was 4

3)闭包是普通对象

l         闭包是在需要时被传递和调用的对象

l         因此可以象下面一样使用:

c = { println("Hello ${it}") }
c.call('James')
c.call('Bob')

l         闭包会被编译成扩展groovy.lang.Closure类的新类

l         下面的省略写法是等价的

c = { println("Hello ${it}") }
c('James')
c('Bob')

4)闭包的参数

l         闭包可以有任意数目的参数

l         缺省情况,闭包具有单个缺省参数:“it

l         你可以在闭包声明的开始部分指定参数列表

c = { a, b, c | println("Hello ${a} ${b} ${c}") }
c('cheese', 234, 'gromit')

l         下面是另一个使用两个参数的有用例子,在《Groovy快速入门》已经讲过:

value = [1, 2, 3].inject('counting: ') { str, item | str + item }
assert value == "counting: 123"
 
value = [1, 2, 3].inject(0) { count, item | count + item }
assert value == 6

3、集合

Groovy支持集合、ListMap和数组

1Lists

l         下面是创建List的例子,[]表示空List表达式

list = [5, 6, 7, 8]
assert list.get(2) == 7
assert list instanceof java.util.List
 
emptyList = []
assert emptyList.size() == 0
emptyList.add(5)
assert emptyList.size() == 1

l         每个List表达式都是java.util.List的实现

2)范围(Ranges

l         Range允许创建连续值的列表

l         由于Range扩展java.util.List,所以Range可以作为List使用

l         使用..Range是包括两个边界,使用...Range只包括开始边界,而不包括结束边界

// an inclusive range
range = 5..8
assert range.size() == 4
assert range.get(2) == 7
assert range instanceof java.util.List
assert range.contains(5)
assert range.contains(8)
 
// lets use an exclusive range
range = 5...8
assert range.size() == 3
assert range.get(2) == 7
assert range instanceof java.util.List
assert range.contains(5)
assert ! range.contains(8)

l         Range可以用于实现java.lang.ComparableJava对象

// an inclusive range
range = 'a'..'d'
assert range.size() == 4
assert range.get(2) == 'c'
assert range instanceof java.util.List
assert range.contains('a')
assert range.contains('d')
assert ! range.contains('e')

l         Range可以用于循环遍历

for (i in 1..10) {
  println "Hello ${i}"
}

3Maps

l         下面是创建Map的例子,[:]表示空Map表达式

map = ["name":"Gromit", "likes":"cheese", "id":1234]
assert map.get("name") == "Gromit"
assert map.get("id") == 1234
assert map instanceof java.util.Map
 
emptyMap = [:]
assert emptyMap.size() == 0
emptyMap.put(5, "foo")
assert emptyMap.size() == 1
assert emptyMap.get(5) == "foo"

l         Map可以象beans一样操作,但key值(类似属性名)必须为有效的String标识

map = ["name":"Gromit", "likes":"cheese", "id":1234]
assert map.name == "Gromit"
assert map.id == 1234
 
emptyMap = [:]
assert emptyMap.size() == 0
emptyMap.foo = 5
assert emptyMap.size() == 1
assert emptyMap.foo == 5

4)使用下标操作符

l         可以在字符串、ListsMaps...中使用下标进行索引

text = "nice cheese gromit!"
x = text[2]
assert x == "c"
assert x.class == String
sub = text[5..10]
assert sub == 'cheese'
 
map = ["name":"Gromit", "likes":"cheese", "id":1234]
assert map['name'] == "Gromit"
 
list = [10, 11, 12]
answer = list[2]
assert answer == 12
 
list = 100..200
sub = list[1, 3, 20..25, 33]
assert sub == [101, 103, 120, 121, 122, 123, 124, 125, 133]

l         可以使用下标操作符更新项目

list = ["a", "b", "c"]
list[2] = "d"
list[0] = list[1]
list[3] = 5
assert list == ["b", "b", "d", 5]

l         可以使用负索引从最后开始计数

text = "nice cheese gromit!"
x = text[-1]
assert x == "!"
name = text[-7..-2]
assert name == "gromit"

l         也可以使用向后范围(开始索引大于结束索引),返回的结果是反转的

text = "nice cheese gromit!"
name = text[3..1]
assert name == "eci"

4、与Java的不同

1)通用

l         Groovy中,==等价于equals()===意味着标识比较(等同Java中的==

l         Java==意味着原类型的相等和对象的标识比较,如a==bab是指向相同对象的引用)

l         传递闭包给方法或使用GroovyMarkup时,{要和方法的调用在同一行上,如:

[1, 2, 3].each { println it }

l         如果要将{放在独立于方法的一行上,要使用括号()

[1, 2, 3].each (
  { println it }
)

l         下面的写法是无效的,会将闭包解释成独立的闭包,而不会将闭包作为方法的参数传递

[1, 2, 3].each
{ 
       println it 
}

2)应该意识到的事情

l         语句后面的分号是可选的,但在同一行上有多个语句需要用分号分隔

l         return关键字可选

l         可以在static方法内使用_this_关键字(何用?)

l         缺省的修饰符是public

l         Groovy中的protected等价包的protectedJavaprotected

l         补充:方法调用时,括号是可选的

3)在Java中无效的Groovy新特性

l         闭包

l         ListMap的本地语法

l         GroovyMarkupGpath的支持

l         正则表达式的本地支持

l         多形式的iteration和强大的switch语句

l         动态和静态类型的支持

l         在字符串中嵌入表达式

l         增加了许多新的帮助方法

l         在属性和添加事件侦听方面,简化了编写bean的语法

阅读(1401) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~