java中只想groovy_Groovy 相对 Java 的一些新玩意

Groovy 是轻量级的 Java

方法,闭包中 return 语句是可选的,如果没有 return,则默认返回方法、闭包的最后一条语句的值

方法和类默认的修饰符都是 public

Groovy 不强迫我们捕获自己不关系的异常,这些异常会被传递给方法的调用者

静态方法中也可以使用 this 来引用当前的静态类 Class 对象。

提供安全导航操作符 .? 来避免对象非空的判断

GDK 一瞥

Java 平台的核心优势是其 Java 开发包(JDK)。Groovy 并没有抛开 Java 单独做一套新的类和库,而是在以后的 JDK 的各种类中添加便捷的方法,这些拓展成为GDK。

其中有一些常用的类,均有不错的扩充

String

Integer

File

List

Map

......

实现循环的集中方式

以下均以实现打印 0~9 的循环为例

for(i in 0..9) { println i }

0.upto(9) { println "$it" }

10.times { println "$it" }

更为简洁的 JavaBean

在 groovy 的 bean 对象中,定义的属性当然可以用 foo.bar的方式来访问,但是这样的访问方式并不是直接访问的 bar 这个变量,而是访问的 getBar/setBar 方法。

只要在类中声明了一个属性,groovy 就会默默地为我们生成对应的 get 和 set 方法,如果该属性是 final 类型,那么只有 get 方法。我们当然也可以自己手动去实现对应的 get/set 方法来实现更丰富的内容。

在foo.bar访问属性的情况下,将 bar 的修饰符改为 private,其实是没有什么意义的,因为这里并不直接访问该变量,因此要对 bar 变量进行一定的保护,手动覆盖对应 getBar/setBar 方法,修改该方法的权限,已达到保护属性的目的。

我们甚至可以不定义属性。假如类中包含一个 getBar()的方法,那么我们在调用该方法时可以使用 foo.bar,但是注意,仅仅实现了 get 方法,只能读取,不能用该方式赋值,如果要进行形如 foo.bar = xxx形式的赋值,那么类中必须要对应一个 setBar() 方法。

使用具名参数对 JavaBean 初始化

如果一个 Bean 对象中含有多个属性,对其属性不同的赋值可能需要提供多种不同参数组合的构造方法,而在 groovy 中却可以便捷的实现。

前提:该类必须有一个无参构造器(没有定义构造器,当然会自动生成一个无参构造器)。如果定义了一个有参构造器,那么编译器便不会提供无参构造器了,需要我们手动提供一个无参构造器。

使用:new Foo(property1:value1,property2:value2,property3:value3);

只需以键值对的方式传入你想赋值的属性的名称和值即可。该语句会在执行完无参构造器之后,对传入的属性依次执行 set 操作。

灵活的方法参数规则

规则一:方法的第一个形参默认可能是 map

对于以下的方法定义:

def bar(a,b,c){

println "received $a $b $c"

}

因为 groovy 的动态类型的语言,在定义方法时可以不指定形参类型,而在使用时动态推断。该方法会调用该对象的 toString 方法。

那么在使用该方法时,如果传入的参数个数多于 3,而且多出的实现是键值对,那么 Groovy 会假设该方法的第一个形参是 map 类型,然后将实参列表中的所有键值对都放到一个 map 中,作为第一个参数传入,然后将剩下的参数按照形参一一对应,进行传参。

这里要注意的问题有两个:

该规则会把所有的键值对都收集起来,即使键值对可能在实参传入的时候,并不是连续的,也没有关系,groovy 依然能识别。然后在将其余的实参依次对应第二个,第三个...形参

按照该规则,可能将键值对全部收集之后,剩下的参数可能与方法定义的参数个数就不匹配了,因为我们在传参时,本想将第二个参数也传入键值对的 map 的,但是不可以。因此在方法定义和使用时应多注意。

规则二:可选形参

一个简单的例子:

def bar(a,b=10){

println a + b

}

assert bar(1,1) == 2

assert bar(1) == 11

规则三:变长参数

groovy 中有两种形式支持方法的变长参数:

// 使用 ... 这也是 Java 本身支持的一种形式

def bar(int a,int ... b){

println "$a and $b"

}

// 如果形参的最后一个参数为数组,那么除了第一个参数被赋值给 a 之外,后面的实参均被当做变长参数的实参传入到 b 数组中

def bar(int a,int b[]){

println "$a and $b"

}

这里要注意的是:如果在调用该方法时,想发送数组而不是离散值时,要注意:groovy 会把形如 [1,2,3] 这种形式的数组当做 List,而不是数组,因此在传入时需要显式的传入 [1,2,3] as int[]

方法可以返回多个值

Java 中,方法至多可以返回一个值,但是 groovy 中可以返回多个值。因为 groovy 的动态性,可以将多个返回值放到数组中,而不用去管具体类型(Java 中数组中的值类型必须一致)。

那么接下来要解决方法的返回值接收的问题。groovy 是这样处理的:将多个变量以逗号分隔,放在圆括号中,置于方法返回的左侧即可

def f2(){

['abc',1]

}

(name,age) = f2()

当()中变量与返回值的数量不一致时:如果有多余的变量,那么被置为 null;如果有多余的值,那么多余的值被丢弃。

操作符重载

groovy 中的操作符是可以重载的,groovy 已经将操作符和预设的方法进行了绑定,只要我们的类中实现了对应的方法(不用实现任何借口),该类的对象就可以调用对应的操作符了。

因此在给类中的方法起名时还是谨慎的好,以免恰好对应了操作符映射的方法名,产生不必要的麻烦。

在 gradle 中比较常用的操作符是 <

自动装箱

在 groovy2.0 之前,基本类型都被当做对象处理。

在 groovy2.0 之后,基本类型只有在必要时才会被看做对象,eg:调用 Integer 的方法,将基本类型传递给对象引用。除此之外,Groovy 会在字节码级别将其保留为基本类型,已达到提升性能的目的。

使用 groovy 代码生成变换

groovy 中提供了很多注解帮助我们生成对应代码,简化我们的开发流程。这里简单提一下最常用的 @Immutable 注解,该注解用来修饰类

一旦用该注解标记了一个类,那么该类的所有字段都将自动标记为 final,并额外为我们创建一个唯一构造器,其参数就是类中声明字段的顺序。

groovy 的缺陷

groovy 的==等价于 Java 的 equals 方法,如果想比较两个引用是否相同,groovy 中提供的方法是 is()

Java 中可以在方法内部用{}包起一块代码,用来定义一个新的作用域,而这样的语法在 groovy 中被认为是在定义闭包,导致编译无法通过

分号并不总是可选的!

看下面这样一个例子:

class Foo{

def bar = 1

{

println "I'am instance initializer"

}

}

原本想在 Foo 类中定义一个对象的初始代码块,但是这样的结构被认为是依附在属性上的一部分,因为前面的 bar 在定义结束后并没有加分号,因此如果遇到这种情况,需要在 bar 定义结束后以分号结尾。

当然,如果是静态代码块就不会有这个问题了。

more

更多内容请参考官方文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值