1. 安全导航操作符 ?.,只有对象引用不为空时才会分派调用。
def a
a?.isEmpty()
2. groovy不强迫捕获我们不关心的异常。
捕获所有Exception
try{
}catch(ex){
}
3. groovy默认都是public的。
4. groovy默认提供构造器。
class Robot{
def type, height, width
}
robot = new Robot(type: 'arm', width: 10, height: 40)
5. groovy传参
出现键值对的形式,groovy会将所有键值对作为第一个形参(Map)的Entry,其余参数按顺序赋给剩余形参。
class Robot{
def access(location, weight, fragile){
print "$fragile, $weight, $location"
}
}
robot.access(x: 30, y: 20, z:10, 5, true)
//可改变顺序
robot.access(5, true, x: 30, y: 20, z:10)
注意:使用键值对传参,最好是当参数仅有一个Map时使用;
如果一定要使用一个Map + 多个参数传递的形式,请显示声明Map类型。
class Robot{
def access(Map location, weight, fragile){
print "$fragile, $weight, $location"
}
}
当实参包含的不是两个对象和一个任意键值对,代码就会报错。
6. 可选形参, 方法可以不用再写重载
def log(x, base = 10){
Math.log(x) / Math.log(base)
}
6.1 变长传参
最后一位形参是数组形式
def receiveVarArgs(int a, int... b){}
def receiveVarArg(int a, int[] b){}
注意:Groovy将 [2, 3]看作是ArrayList的一个实例对象,因此调用时:
receiveVarArgs(1, [2, 3, 4] as int[])
可参考Groovy创建数组、列表的区别:
int[] arr = [1, 2, 3]
def arr1 = [1, 2, 3] as int[]
def arr2 = [1, 2, 3] //ArrayList类型
7. 多赋值。返回数组,被多赋值给各个变量。
等号左边变量多的,将设为null(不能默认null的,抛异常),右边值多的,将丢弃。
def splitName(fullName){
fullName.split(' ')
}
def (firstName, lastName) = splitName('James Bond')
因此可以延伸为交换变量
def a = 1
def b = 2
(a, b) = [b, a]
8. 实现接口
一接口,单方法
def diaplyMouseLocation = {positionLabel.setText("$it.x, $it.y")}
frame.addMouseListener(diaplyMouseLocation as MouseListener)
一接口,多方法
def handleFocus = [
focusGained : {}
focusLost : {}
]
动态实现接口, asType()作为什么的接口实现
events = ['WindowListener', 'ComponentListener']//可以是更动态的一些输入
handler = {msgLabel.setText("$it")}
for(event in events){
handlerImpl = handler.asType(Class.forName("java.awt.event.${event}"))
frame."add${event}"(handlerImpl)
}
9. 默认布尔处理
groovy基本都为对象,除引用对象不为空为true外,有些对象还有如下情况也为true。
| Boolean | 值为true |
| Collection | 不为空 |
| Map | 映射不为空 |
| Char | 不为0 |
| 字符串 | 长度大于0 |
| 数字 | 不为0 |
| 数组 | 长度大于0 |
| 其他类型 | 不为null |
| 自定制 | 通过asBoolean()方法来重写 |
10. forEach
for(String greet : greetings){}
for(def greet : greetings){}
不想指定类型:
for(greet in greetings){}
或者 内部迭代器 each()
10. 静态导入支持别名
import static Math.random as rand
double value = rand()
11. java的编译时注解被忽略,如Override。
12. groovy既支持动态类型,又支持泛型。泛型在执行时进行检查生效。
13. Groovy可以重载操作符,因为每个操作符都被映射到一个标准的方法。
14. 使用注解生成代码
@Canonical 标注于类上,用于生成toString():逗号分隔各属性,可排除属性
@Canonical(excludes='lastName, age')
class Person{}
@Delegate 用于引入被委托类相应的方法包装器,用于委派任务。引入的具体实例方法与顺序有关。
查找还未有的方法进行一次引入。
class Worker{
def work(){}
def analyze(){}
}
class Expert{
def analyze(){}
}
class Manager{
@Delegate Expert expert = new Expert()//引入Expert实例的analyze方法
@Delegate Worker worker = new Worker()//引入Worker实例的work方法
}
@Immutable 标注在类上,用于便捷生成不可变值对象,即属性final。同时提供hashCode()、equals()、toString()方法。
@Immutable
class CreditCard{
String cardNumber
int creditLimit
}
@Lazy 标注于属性上,懒加载
class Heavy{}
class AsNeeded {
@Lazy Heavy heavy = new Heavy()
}
@Singleton 标注于类上,实现单例模式
@Singleton(lazy = true)
class TheUnique{
}
15. ==
== 等于调用java的equals(),除非实现Comparable接口的类型,== 等于compareTo()
is()等于java的==
16. groovy匿名内部类使用可能会有问题,会将{……}实现体当做闭包。