1. Groovy简介
Groovy是一种语言,其语法类似于Java,但比Java更简单。它通常被视为脚本/灵活/动态的语言。 注:语法等介绍,参见 附录groovy入门
2. 创建Entity
用Groovy创建Entity和创建JAVA bean类似,并且更简单。 创建Entity类,需要继承com.brs.magic.RootEntity类。 例如创建一个客户的Entity:
package com.brs.test
class Test extends com.brs.magic.RootEntity {
}
String asn String id String name
3. 编写Service
创建service类,使用com.brs.magic.Service接口。
package com.brs.test
class TestService implements com.brs.magic.Service {
}
def test(Test t){ }
t.persistOrMerge();//保存或者替换 return t;
4. 页面调用Service方法
在html页面,使用DWR.call方法来调用service方法。
在使用DWR.call调用service方法时,应注意异步的问题。在后台数据返回前,使用将产生错误。
var obj = {
asn:\"asnString\", name:\"这是个示例\" };
DWR.call('testService.test',obj,function(v){
alert(v.name); });
附录:
Groovy入门
1、类 (1)类
Groovy的类定义和Java类似
方法可以基于类(static)或实例 可以为public、protected或private
支持常用的Java修饰符,如synchronized Groovy的不同地方:缺省是public
Groovy支持JavaBean机制:GroovyBean
每个Groovy类都是字节码/JVM级的Java类,任何方法对Java都是有
效的,反之亦然
你可以指定方法的参数类型和返回类型,这样可以在通常的Java代码中更
好的工作
你可以用上面的方式来实现接口或重载方法
如果省略方法的类型,就会使用缺省的java.lang.Object (2)脚本
Groovy支持纯脚本,而不需要声明类,如Foo.groovy包含下面的脚本:
println \"Nice cheese Gromit!\"
运行脚本的过程:
编译成Foo.class(还会有一些内类),该类扩展groovy.lang.Script 执行自动生成的main方法 实例化Foo类
调用run方法执行脚本内容
可以在Java代码中执行脚本,同时还可以传递变量值到脚本中 Foo.groovy内容修改如下
println \"Nice ${cheese} Gromit!\"
下面是执行脚本的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\ Script foo = new Foo(binding); foo.run(); } }`
UseFoo运行的结果是:Nice Cheddar Gromit!
执行脚本的方法是创建Foo类实例,调用其run方法
Foo类有一个带Binding参数的构造函数,可以通过Binding类的
setVariable方法设置值给脚本中的属性变量
Foo类有一个不带参数的构造函数,在不传递属性变量值时使用
在脚本结束后,脚本中创建的任何变量都会在Binding中,以供在Java中
访问
再将Foo.groovy内容修改如下
println \"Nice ${cheese} Gromit!\" cheese = \"changed\"
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\
Script foo = new Foo(binding); foo.run();
println binding.getVariable(\"cheese\"); } }
UseFoo运行的结果是:
Nice Cheddar Gromit!
changed
(3)脚本中的函数
不同于基于Class的Groovy,纯脚本中的函数用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)概述
闭包是一种传递执行代码块的强大方法。
可以把闭包看作Java中的匿名内类,但是只有单一的(匿名)方法。 闭包可以被用作循环的一种替代方法
[1, 2, 3, 4].each { println(it) }
使用闭包可以使异常处理和关闭资源变得更简单,具体例子请参看Groovy
SQL
(2)比较闭包和匿名内类
不同于Java匿名内类,Groovy 支持“true closures”:状态可以被传递
到闭包外部
局部变量在闭包创建时可以被使用和修改;闭包中创建的任何变量可以作
为局部变量,对外部可见 看下面的例子:
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)闭包是普通对象
闭包是在需要时被传递和调用的对象 因此可以象下面一样使用:
c = { println(\"Hello ${it}\") } c.call('James') c.call('Bob')
闭包会被编译成扩展groovy.lang.Closure类的新类 下面的省略写法是等价的
c = { println(\"Hello ${it}\") } c('James') c('Bob')
(4)闭包的参数
闭包可以有任意数目的参数
缺省情况,闭包具有单个缺省参数:“it” 你可以在闭包声明的开始部分指定参数列表
c = { a, b, c | println(\"Hello ${a} ${b} ${c}\") } c('cheese', 234, 'gromit')
下面是另一个使用两个参数的有用例子:
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支持集合、List、Map和数组 (1)Lists
下面是创建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
每个List表达式都是java.util.List的实现 (2)范围(Ranges)
Range允许创建连续值的列表
由于Range扩展java.util.List,所以Range可以作为List使用
使用..的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)
Range可以用于实现java.lang.Comparable的Java对象
// 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')
Range可以用于循环遍历
for (i in 1..10) { println \"Hello ${i}\" }
(3)Maps
下面是创建Map的例子,[:]表示空Map表达式
map = [\"name\":\"Gromit\ 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\"
Map可以象beans一样操作,但key值(类似属性名)必须为有效的String
标识
map = [\"name\":\"Gromit\ 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)使用下标操作符
可以在字符串、Lists、Maps...中使用下标进行索引
text = \"nice cheese gromit!\" x = text[2] assert x == \"c\" assert x.class == String sub = text[5..10] assert sub == 'cheese'
map = [\"name\":\"Gromit\ 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]
可以使用下标操作符更新项目
list = [\"a\ list[2] = \"d\" list[0] = list[1] list[3] = 5
assert list == [\"b\
可以使用负索引从最后开始计数
text = \"nice cheese gromit!\" x = text[-1] assert x == \"!\" name = text[-7..-2] assert name == \"gromit\"
也可以使用向后范围(开始索引大于结束索引),返回的结果是反转的
text = \"nice cheese gromit!\" name = text[3..1] assert name == \"eci\"
4、与Java的不同 (1)通用
在Groovy中,==等价于equals(),===意味着标识比较(等同Java中的==) 在Java中==意味着原类型的相等和对象的标识比较,如a==b(a和b是指
向相同对象的引用)
传递闭包给方法或使用GroovyMarkup时,{要和方法的调用在同一行上,
如:
[1, 2, 3].each { println it }
如果要将{放在于方法的一行上,要使用括号()
[1, 2, 3].each ( { println it } )
下面的写法是无效的,会将闭包解释成的闭包,而不会将闭包作为方
法的参数传递
[1, 2, 3].each {
println it }
(2)应该意识到的事情
语句后面的分号是可选的,但在同一行上有多个语句需要用分号分隔 return关键字可选
可以在static方法内使用_this_关键字(何用?) 缺省的修饰符是public
Groovy中的protected等价包的protected和Java的protected 补充:方法调用时,括号是可选的 (3)在Java中无效的Groovy新特性 闭包
List和Map的本地语法
GroovyMarkup和Gpath的支持 正则表达式的本地支持
多形式的iteration和强大的switch语句 动态和静态类型的支持 在字符串中嵌入表达式 增加了许多新的帮助方法
在属性和添加事件侦听方面,简化了编写bean的语法 5、Groovy Math
Groovy支持访问所有的Java Math类和操作
为了使math操作在脚本编写时尽可能直观,Groovy math模型支持文字化
math操作
缺省计算使用的是精确的小数(BigDecimal),如:
1.1 + 0.1 == 1.2
返回的是true,而不是false(不象在Java中使用float或double) (1)数字的文字表示
Groovy的小数文字表示是java.math.BigDecimal的实例,而不是浮点类型
(Float或Double)
Float和Double可以使用后面讲的后缀(F和D)方法来创建 小数的指数形式也支持,如12.3e-23
十六进制和八进制也支持,十六进制前缀0x,八进制前缀0
整数类型可以使用后面讲的后缀(I、L和G)方法来创建,如果不指定根
据数值的大小使用合适的类型 数字类型的后缀文字表示 _Type_ _Suffix_ _BigInteger_ G _Long_ L _Integer_ I _BigDecimal_ (缺省) _Double_ D _Float_ F 例子: assert 42I == new Integer(\"42\"); assert 123L == new Long(\"123\");
assert 21474838 == new Long(\"21474838\"); //Long type used, value too large for an Integer
assert 456G == new java.math.BigInteger(\"456\");
assert 123.45 == new java.math.BigDecimal(\"123.45\"); //default BigDecimal type used
assert 1.200065D == new Double(\"1.200065\"); assert 1.234F == new Float(\"1.234\"); assert 1.23E23D == new Double(\"1.23E23\");
(2)Math操作
Groovy的Math实现很接近Java 1.5 BigDecimal Math模型的实践
Java.lang.Number包括其子类的二元操作(除了除法)会根据下表自动转
换参数类型 _BigDecimal_ _BigInteger_ _Double_ _Float_ _Long_ _Integer_ _BigDecimal_ BigDecimal BigDecimal Double Double BigDecimal BigDecimal Double Double BigInteger BigInteger _BigInteger_ BigDecimal BigInteger Double Double Double Double Double Double _Double_ Double Double Double Double Double Double _Float_ BigDecimal BigInteger Double Double Long Long _Long_ BigDecimal BigInteger Double Double Long Integer _Integer_ 注意:Byte、Character、Short都作为Integer类型 (3)除法 除法操作“/”和“/=”在操作数中有Float或Double类型时,结果为Double
类型;其它情况,结果为BigDecimal类型 BigDecimal类型的操作会这样做:
BigDecimal.divide(BigDecimal right, 其中 例子: 1/2 == new java.math.BigDecimal(\"0.5\"); 1/3 == new java.math.BigDecimal(\"0.3333333333\"); 2/3 == new java.math.BigDecimal(\"0.6666666667\"); 整型除法使用“\\”和“\\=”操作,返回整型类型 由于“\\”是Java中的转义符,在字符串中使用需要转义 \" x = 8\\\\3 \" (4)数字文字表示语法 IntegerLiteral: Base10IntegerLiteral HexIntegerLiteral OctalIntegerLiteral Base10IntegerLiteral: Base10Numeral IntegerTypeSuffix (optional) HexIntegerLiteral: HexNumeral IntegerTypeSuffix (optional) OctalIntegerLiteral: OctalNumeral IntegerTypeSuffix (optional) IntegerTypeSuffix: one of i I l L g G Base10Numeral: 0 NonZeroDigit Digits (optional) Digits: Digit Digits Digit Digit: 0 NonZeroDigit NonZeroDigit: one of \\1 2 3 4 5 6 7 8 9 HexNumeral: 0 x HexDigits 0 X HexDigits HexDigits: HexDigit HexDigit HexDigits HexDigit: one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F OctalNumeral: 0 OctalDigits OctalDigits: OctalDigit OctalDigit OctalDigits OctalDigit: one of 0 1 2 3 4 5 6 7 DecimalPointLiteral: Digits . Digits ExponentPart (optional) DecimalTypeSuffix (optional) . Digits ExponentPart (optional) DecimalTypeSuffix (optional) Digits ExponentPart DecimalTypeSuffix (optional) Digits ExponentPart (optional) DecimalTypeSuffix (optional) ExponentPart: ExponentIndicator SignedInteger ExponentIndicator: one of e E SignedInteger: Signopt Digits Sign: one of + - DecimalTypeSuffix: one of f F d D g G 6、I/O Groovy提供许多有用的方法来处理I/O,包括标准的Java Reader/Writer、 InputStream/OutputStream、File和URL类 使用闭包允许处理资源时确保正确关闭而不管是否有异常,例如下面的例 子遍历文件的每一行,即使闭包中发生异常,文件也能正确关闭: import java.io.File new File(\"foo.txt\").eachLine { println it } 使用Reader/Writer:通过闭包处理资源 import java.io.File new File(\"foo.txt\").withReader { reader | while (true) { line = reader.readLine() ... } } Groovy提供简单的方法执行命令行进程,表达式返回java.lang.Process 实例,具有in/out/err流(译者:没有测试过) process = \"ls -l\".execute() process.in.eachLine { line | println line } 7、逻辑分支 (1)if-else语句 Groovy提供Java相同的if-else语句 x = false y = false if ( !x ) { x = true } assert x == true if ( x ) { x = false } else { y = true } assert x == y Groovy也支持三元操作符 y = 5 x = (y > 1) ? \"worked\" : \"failed\" assert x == \"worked\" (2)switch语句 Groovy的switch语句兼容Java代码,不同之处在于Groovy的switch语 句能够处理各种类型的switch值,可以做各种类型的匹配 case值为类名匹配switch值为类实例 case值为正则表达式匹配switch值的字符串匹配该正则表达式 case值为集合匹配switch值包含在集合中,这包括ranges 除了上面的,case值与switch值相等才匹配 x = 1.23 result = \"\" switch ( x ) { case \"foo\": result = \"found foo\" // lets fall through case \"bar\": result += \"bar\" case [4, 5, 6, 'inList']: result = \"list\" break case 12..30: result = \"range\" break case Integer: result = \"integer\" break case Number: result = \"number\" break default: result = \"default\" } assert result == \"number\" switch语句的工作原理:switch语句在做匹配case值时调用 isCase(switchValue)方法,缺省调用equals(switchValue),但是已经被重载成各种类型,如类,正则表达式、集合等等 可以创建自定义的匹配类,增加isCase(switchValue)方法来提供自定义的 匹配类型 8、循环 (1)while和do 循环 Groovy支持Java相同的while和do 循环 x = 0 y = 5 while ( y-- > 0 ) { x++ } assert x == 5 x = 0 y = 5 do { x++ } while ( --y > 0 ) assert x == 5 (2)for循环 Groovy的for循环更简单,而且能够和各种类型的数组、集合、Map等一 起工作 // iterate over a range x = 0 for ( i in 0..9 ) { x += i } assert x == 45 // iterate over a list x = 0 for ( i in [0, 1, 2, 3, 4] ) { x += i } assert x == 10 // iterate over an array array = (0..4).toArray() x = 0 for ( i in array ) { x += i } assert x == 10 // iterate over a map map = ['abc':1, 'def':2, 'xyz':3] x = 0 for ( e in map ) { x += e.value } assert x == 6 // iterate over values in a map x = 0 for ( v in map.values() ) { x += v } assert x == 6 // iterate over the characters in a string text = \"abc\" list = [] for (c in text) { list.add(c) } assert list == [\"a\ 9、操作符重载 Groovy支持操作符重载,使得数值、集合、Map和其它种类的数据结构更 容易使用 在Groovy中的各种操作符被映射到对象中调用的正规方法 Operator Method a + b a.plus(b) a - b a.minus(b) a * b a.multiply(b) a / b a.divide(b) a++ or ++a a.next() a-- or --a a.previous() a[b] a.getAt(b) a[b] = c a.putAt(b, c) a << b a.leftShift(b) a == b a.equals(b) a != b ! a.equals(b) Java中的 a == b a === b a <=> b a.compareTo(b) a > b a.compareTo(b) > 0 a >= b a.compareTo(b) >= 0 a < b a.compareTo(b) < 0 a <= b a.compareTo(b) <= 0 注意:所有比较操作符已经对null处理了,以避免抛出java.lang.NullPointerException a = null b = \"foo\" assert a != b assert b != a assert a == null 在不同类型的数值比较之前,Groovy会自动将数值的类型转换为更大范围 的数值类型,因此,下面的例子是有效的: Byte a = 12 Double b = 10 assert a instanceof Byte assert b instanceof Double assert a > b 10、正则表达式 Groovy支持使用~”...”本地表示的正则表达式,另外还支持“=~”操作符(创 建Matcher) import java.util.regex.Matcher import java.util.regex.Pattern // same as assert (\"cheesecheese\" =~ \"cheese\").find() assert \"cheesecheese\" =~ \"cheese\" // lets create a regex Pattern pattern = ~\"a*b\" assert pattern instanceof Pattern assert pattern.matcher(\"aaaab\").matches() // lets create a Matcher matcher = \"cheesecheese\" =~ \"cheese\" assert matcher instanceof Matcher answer = matcher.replaceAll(\"edam\") assert answer == \"edamedam\" Matcher缺省会调用find()方法返回boolean值,因此可以使用=~与Perl 的=~操作符的简单使用保持一致 对于上面的模式匹配的例子主要是演示Pattern的用法,其实可以简化为 assert (\"aaaab\" =~ \"a*b\").matches() 11、语句 (1)分号 Groovy使用类似Java的语法,但是语句的分号是可选的 如果每行一个语句,就可以省略分号;如果一行上有多个语句,就要用分 号来分隔 x = [1, 2, 3] println x y = 5; x = y + 7 println x assert x == 12 一个语句可以跨越多行,对于方法的参数列表或复杂的表达式,可能会这 样做 x = [1, 2, 3, 4, 5, 6] println( x ) if (x != null && x.size() > 5) { println(\"Works!\") } else { assert false: \"should never happen ${x}\" } (2)方法调用 方法调用的语法和Java类似,支持静态和实例方法 class Foo { calculatePrice() { 1.23 } static void main(args) { foo = new Foo() p = foo.calculatePrice() assert p > 0 println \"Found price: \" + p } } 注意,return关键字在方法的最后是可选的;同样,返回类型也是可选(缺 省是Object) 在Groovy中方法的调用可以省略括号,只要有参数,并且没有歧义 (3)传递命名参数 在调用方法时,可以传递命名参数,参数的名字和值用分号分隔(象Map 语法),参数名是唯一标识字符串 bean = new Expando(name:\"James\ println \"Hey \" + bean.name assert bean.id == 123 当前这种方法传递只实现具有Map的方法调用或JavaBean构造 (4)传递闭包给方法 请参考《Groovy快速入门》 (5)动态方法分派 如果变量没有使用类型强制,动态方法分派被使用,这经常被指为动态类 型,而Java缺省使用静态类型 可以在代码中混合使用动态和静态类型 dynamicObject = \"hello world\".replaceAll(\"world\ dynamicObject += \"!\" assert dynamicObject == \"hello Gromit!\" String staticObject = \"hello there\" staticObject += \"!\" assert staticObject == \"hello there!\" (6)属性 通过“.属性名”访问属性 bean = new Expando(name:\"James\ name = bean.name println(\"Hey ${name}\") bean.location = \"Vegas\" println bean.name + \" is now in \" + bean.location assert bean.location == \"Vegas\" 上面的特殊bean Expando在运行时,动态添加属性 它实际上是一个行为象动态bean的Map:增加name/value对和等效的 getter/setter方法,就象定义一个真正的bean (7)安全导航 如果你在访问复杂对象时,不想遇到NullPointerException异常,你可以 使用“->”而不是“.”来导航 foo = null bar = foo->something->myMethod() assert bar == null 12、字符串 (1)基本用法 Groovy中的字符串允许使用双引号和单引号 println \"he said 'cheese' once\" println 'he said \"cheese!\" again' Groovy支持\引用(其中X是16进制数),用来表示特殊字符,例 如\@与@字符相同 (2)多行字符串 Groovy中的字符串可以分成多行 foo = \"hello there how are things?\" println(foo) (3)Here-docs 如果有一大块文本(如HTML的)不想编码,你可以使用Here-docs name = \"James\" text = << (4)GString 使用${expression}语法,可以在字符串中包含任意的表达式,类似于JSP EL、Velocity 任何有效的Groovy表达式都能够使用${...}包含到方法调用中 使用包含${expression}的字符串时,CString对象就会被创建,以包含在 字符串中使用的文本和值 CString使用惰性求值方式,只有在调用toString()方法时才会求值 1、 集合 (1)List (java.util.List) list = [1, 2, 'hello', new java.util.Date()] assert list.size() == 4 assert list.get(2) == 'hello' 注意:一切都是对象(数字会自动转换) (2)Map (java.util.Map) map = ['name':'James', 'location':'London'] assert map.size() == 2 assert map.get('name') == 'James' (3)遍历集合 list = [1, 2, 3] for (i in list) { println i } 2、 闭包(Closures) 闭包类似Java的内类,区别是闭包只有单一的方法可以调用,但可以有任 意的参数 closure = { param | println(\"hello ${param}\") } closure.call(\"world!\") closure = { greeting, name | println(greeting + name) } closure.call(\"hello \ 闭包用“{}”括起,“|”前面是参数,后面是处理语句,使用call调用 第一个例子演示了在字符串内使用参数的形式:${param} 第二个例子演示了多参数形式:用“,”分隔参数 如果只有一个参数,可以不写,而使用缺省的参数“it”,如下面的例子: closure = { println \"hello \" + it } closure.call(\"world!\") 3、 each 遍历集合,逐个传递给闭包 [1, 2, 3].each { item | print \"${item}-\" } 上面例子的输出结果是:1-2-3- 4、 collect 遍历集合,逐个传递给闭包,处理后的结果返回给对应的项 value = [1, 2, 3].collect { it * 2 } assert value == [2, 4, 6] 5、 find 根据闭包断言,返回集合中找到的第一个项目 value = [1, 2, 3].find { it > 1 } assert value == 2 6、 findAll 根据闭包断言,返回集合中所有找到的项目 value = [1, 2, 3].findAll { it > 1 } assert value == [2, 3] 7、 inject 遍历集合,第一次将传递的值和集合项目传给闭包,将处理结果作为传递 的值,和下一个集合项目传给闭包,依此类推 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 8、 every 如果集合中所有项目都匹配闭包断言,就返回true,否则返回false value = [1, 2, 3].every { it < 5 } assert value value = [1, 2, 3].every { item | item < 3 } assert ! value 9、 any 如果集合中任何项目匹配闭包断言,就返回true,否则返回false value = [1, 2, 3].any { it > 2 } assert value value = [1, 2, 3].any { item | item > 3 } assert value == false 10、 min/max 返回集合中的最小/最大项目(对象必须可比较) value = [9, 4, 2, 10, 5].max() assert value == 10 value = [9, 4, 2, 10, 5].min() assert value == 2 value = ['x', 'y', 'a', 'z'].min() assert value == 'a' 11、 join 连接集合中的值成一个字符串 value = [1, 2, 3].join('-') assert value == '1-2-3' 12、 yield 在Python和Ruby中通过yield语句创建“yield”风格的iterators,在 Groovy同样有效,只是使用的是闭包 class Foo{ static void main(args) { foo = new Foo() for (x in foo.myGenerator) { print(\"${x}-\") } } myGenerator(Closure yield) { yield.call(\"A\") yield.call(\"B\") yield.call(\"C\") } } 例子的输出结果是:A-B-C- Cloures原型可以省略,call和括号同样可选,这样更象Python/Ruby class Foo { myGenerator(yield) { yield \"A\" yield \"B\" yield \"C\" } static void main(args) { foo = new Foo() foo.myGenerator { println \"Called with ${it}\" } } }
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务