groovy in action
在JVM中运行groovy类有两种方式: ?使用groovyc编译所有的*.groovy为java的*.class文件,把这些*.class文件放在java类路径中,通过java类加载器来加载这些类。 ?通过groovy的类加载器在运行时直接加载*.groovy文件并且生成对象,在这种方式下,没有生成任何*.class,但是生成了一个java.lang.Class对象的实例。(java的动态编译加载功能) groovy在源代码级增强java,但是在字节码是与java一样的。 Groovy的语法是面向行的,但是执行groovy代码却不是这样的,不像别的脚本语言,groovy代码不是一行一行的解释执行的。 groovy代码被完整地转换,通过转换器产生一个java类,产生的这个类是groovy和java之间的粘合剂。产生的groovy类的格式与java字节码的格式是一样的。 groovy的类加载器能够从*.groovy文件加载类(在放入缓存之前进行转换和生成类)。 在运行时生成groovy类 1.MyScript.groovy被传递给groovy的转换器 2.转换器产生一个抽象语法树(AST)来表示在MyScript.groovy中的所有代码; 3.Groovy类生成器根据AST产生java字节码,根据脚本的内容,结果可能是多个类,现在类通过groovy类加载器是可以使用的了; 4.Java运行时像调用一个java类MyScript一样来调用第三步产生的类; 在使用之前类已经完整地构建并且在运行时不能进行更改(不排除在.groovy被修改之后对类在运行时的替换)。 groovy中一切事情都是对象,所有的操作符都是作为方法调用进行处理的。 注意BigDecimal是默认的非整数类型——除非指定后缀强制类型为Float或者Double,否则将使用BigDecimal。 给定期望信息的时候groovy是如何处理类型的: 在groovy中出现的字面符号(数字、字符串等等)没有任何问题,它们都是对象,它们仅仅传递给java时才进行装箱和拆箱,操作符是方法调用的快速途径。 操作符是方法的便利写法(在groovy中所有的都是对象,操作符是对象方法的便利写法): “==”或者equals指示对象是否同等(值相等),而不是是否指向同一个对象。 实现equals的目的是保证这个对象可以与null对象进行对比。equals操作的缺省实现是不抛出NullPointerException。 times方法仅仅用于做重复的动作,upto方法是递增一个数字,downto是递减一个数字,step是按一个步进从一个数递增到另外一个数。 在面向对象语言,方法对象模式(Method-Object-pattern)通常用来模拟一个行为:为一个目的定义一个独立的方法接口,这个接口的实例能够传递一组参数给方法,然后调用这个接口方法。 一个闭包是一个用花括号围起来的语句块,为了传递参数给闭包,闭包有一组可选的参数列表,通过“->”表示列表的结束。 脚本允许使用没有声明的变量,在这种情况下变量被假定从脚本的binding属性获取,如果在binding中没有发现相应的变量,那么把变量增加到bindding中,binding是一个数据存储器,它能把变量在脚本调用者和脚本之间进行传递。 缺省属性范围在groovy有特殊的意思,在没有指定范围修饰符的属性声明的时候,groovy会根据需要生成相应的访问方法(getter方法和setter方法) 定义变量的类型是可选的,不管怎样,标示符在声明的时候不必独一无二,当没有类型和修饰符时,必须使用def来作为替换,实际上用def来表明属性或者变量是没有类型的(尽管在内部将被声明为Object类型)。 重写下标操作符: ? 重写get方法意味着重写了dot-fieldName操作符,重写了set方法意味着重写了field assignment操作符。 class PretendFieldCounter{ public count = 0; Object get(String name){ return 'pretend value'; } void set(String name,Object value){ count++ } } class Test { static main(args) { def pretender = new PretendFieldCounter(); println pretender.isNoField == 'pretend value'; println pretender.count == 0; pretender.isNoFieldEither = 'just to increase counter' println pretender.count == 1 } } 结果全都是true 第五章闭包 一个闭包是被包装为一个对象的代码块,实际上闭包像一个可以接受参数并且能够有返回值的方法。 闭包是一个普通对象。 闭包的简短写法:
原本:
class Closure { static main(args) { Closure envelope = {person-> printf(person)} ["a","b"].each(envelope); } } 可以写成如下形式: class Closure2 { static main(args) { ["a","b"].each{printf(it)}; } } 使用闭包作为单个参数的方法调用(在groovy中传递一个闭包给一个方法是非常平常,没有特殊规则。)
如果闭包仅仅需要一个参数,groovy提供了一个缺省的名称——it
声明闭包
在一个方法调用的后面,放置闭包代码在一对花括号里,闭包的参数和代码通过箭头(->)进行分隔。
第二种声明闭包的方式是直接将它赋给一个变量:
def printer = {line -> println line} 通过方法的返回值 def Closure getPrinter(){ return {line -> println line} }
花括号指明构建了一个新的闭包对象
提示:或括号能用来标明构建了一个新的闭包对象或者一个groovy代码块,代码块可以是类、接口、static、对象的初始化代码、方法体,或者与groovy的关键字(if、else、synchronzied、 for、 while、 switch、 try、 catch和finally)一起出现,其他出现的形式就是闭包。
第三种声明闭包的方式是重用已有的声明:一个方法。
方法闭包被限制在一个实例方法,但是可以实现运行时重载。
如果闭包的参数进行了显示的类型声明,那么类型的检查发生在运行时而不是在编译的时候
调用闭包:
一个引用x指向一个闭包,可以通过x.call()来调用闭包或者简单的x()
class CallingClosures { static main(args) { def adder = {x,y -> return x+y} assert adder(4,3) == 7 assert adder.call(2,6) == 8 } }
有缺省值的闭包:
class Closure4 { static main(args) { def adder = {x,y=5 -> return x+y} assert adder(4,3) == 7 assert adder.call(7) ==12 } } 闭包典型的调用方式:
闭包参数的数量:
class Closure5 { def caller(def closure){ closure.getParameterTypes().size() } void test(){ assert caller{ one ->} ==1 assert caller{ one,two ->} ==2 } static main(args) { new Closure5().test() } } curry函数(函数式编程) class Closure6 { static main(args) { def configurator = { format,filter,line-> filter(line)? format(line):null } def appender = {config,append,line -> def out = config(line) if(out) append(out) } def dateFormatter = {line -> "${new Date()}:$line"} def debugFilter = { line -> line.contains('debug')} def consoleAppender = { line -> println line} def myConf = configurator.curry(dateFormatter,debugFilter) def myLog = appender.curry(myConf,consoleAppender) myLog('here is some debug message') myLog('this will not be printed') } } 通过isCase方法进行分类 class Closure7 { static main(args) { assert [1,2,3].grep{ it < 3} == [1,2] switch(10){ case {it%2 == 1} : assert false } } } 花括号显示了闭包声明的时间,不是执行的时间 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |