Groovy
JVM运行
动态语言+脚本语言
支持函数式编程,不需要main函数
类不支持default作用域,默认public
受检查类型异常(Checked Exception)可以不捕获
行末分号不是必须的,无分号时groovy计算一行如果是有效表达式则认为下一行是新表达式,否则将联合下一行共同作为一个表达式
方法调用的圆括号不是必须的,但无参方法调用或第一个参数是集合类型时必须
方法定义中的return语句不是必须的
for循环中不能用逗号分隔多个运算符
不支持DO...WHILE循环,但可以使用while...for运算代替
不支持内部类和匿名类,但支持闭包和在一个文件中定义多个类
使用groovyConsole开发
使用Intellij IDEA等工具安装groovy插件进行groovy开发
【关键字】
as, assert, break, case, catch, class, const, continue,
def, default, do, else, enum, extends, false, finally,
for, goto, if, implements, import, in, instanceof,
interface, new, null, package, return, super, switch,
this, throw, throws, trait, true, try, while
【标识符】
只能以字母、美元符$、下划线开始
def name, $name, _name
map.'name'
map."name"
map.'''name'''
map."""name"""
map./name/
map.$/name/$
使用斜线/定义正则表达式,避免java中的多次转义,如"\\\\\\w"相当于/\\\w/
assert ~"London" instanceof java.util.regex.Pattern
assert ~/\w+/ instanceof java.util.regex.Pattern
assert "Speaking plain English" =~ /plain/ //=~匹配
assert !("Speaking plain English" ==~ /plain/) //==~精确匹配
assert "Speaking plain English" ==~ /.*plain.*/
【字符串】
Groovy有java.lang.String和groovy.lang.GString两中字符串对象类型
单引号字符串是String类型,不支持Groovy运算符
双引号字符串没有$是String类型,有$是GString类型
多重单引号字符串是String类型,不支持$操作,支持多行字符串
多重双引号字符串支持$操作,支持多行字符串
斜线字符串和双引号字符串类似,通常用在正则表达式
${}用于字串或表达式,$用于A.B形式
def name = 'tom'
def greeting = 'Hello $name'
assert greeting == 'Hello $name'
def greeting = "Hello ${name}"
assert greeting == 'Hello tom'
def person = [name: 'tom', age: 36]
assert "$person.name is $person.age years old" == 'tom is 36 years old'
String str = 'Hello tom'
str = str.replace(' ' as char, '+' as char)
assert str == "Hello+tom"
assert 123 as String == "123"
char c1 = 'A'
def c2 = 'B' as char
def c3 = (char)'C'
assert c3 instanceof Character
GString支持延迟运算
def number = 1
def eagerGString = "value == ${number}"
def lazyGString = "value == ${ -> number }"
assert eagerGString == "value == 1"
assert lazyGString == "value == 1"
number = 2
assert eagerGString == "value == 1"
assert lazyGString == "value == 2"
GString和String即使字符串一样HashCode也不会一样,不能使用GString作为map的key
assert "${1}".hashCode() != "1".hashCode()
def key = "a"
def m = ["${key}": "letter ${key}"]
assert m["a"] == null
【数字】
基本类型也是对象,直接调用对象方法
支持byte、char、short、int、long、java.lang.BigInteger、
float、double、java.lang.BigDecimal
int i = 1
int xInt = 011
assert xInt == 9
assert 1e3 == 1_000.0
assert 3e+1 == 30.0
assert 4E-2 == 0.04
assert (-12).abs() == 12
assert 1234.compareTo("1235" as int) < 0
【布尔】
支持对对象进行布尔求值, null对象、空字符串、0、空集合、迭代、枚举、正则匹配无返回时为false
assert (!true) == false
assert (0) == false
assert ('') == false
assert (null) == false
【Arrays】
int[] numbers = [1, 2, 3]
def numbers = [1, 2, 3] as int[]
assert numbers instanceof int[]
assert !(numbers instanceof List)
assert numbers[0] == 1
assert numbers[-1] == 3
assert numbers.size() == 3
def multi = [[0, 1], [2, 3]]
【Lists】
def numbers = [1, 2, 3]
assert numbers instanceof List
assert numbers instanceof java.util.ArrayList
numbers << 4 //给List追加item
assert numbers[3] == 4
assert numbers[1,2] == [2,3] //获取子集
assert numbers[1..3] == [2,3,4]
def numbers = [1, 2, 3] as LinkedList //使用as强转类型
assert numbers instanceof java.util.LinkedList
def arrayList = [1, "a", true] //List中存储任意类型
def multi = [[0, 1], [2, 3]] //多维List支持
【Range】
def range = 1..5 //12345
assert range[0] == 1
assert range.get(0) == 1
assert range.size() == 5
assert range instanceof java.util.List
assert range.contains(5)
range = 1..< 5 //1234
assert range.from == 1
assert range.to == 4
for (int i in 0..<range.size()) {
println "number $i is '${range[i]}'"
}
List subList = range[1..3]
【Maps】
groovy将map的key作为字符串处理,把一个变量作为key,必须添加括弧
def key = 'a'
def letters = [key: 'A']
assert !letters.containsKey('a')
assert letters.containsKey('key')
letters = [(key): 'A']
assert letters.containsKey('a')
assert !letters.containsKey('key')
letters.b = "B"
assert letters instanceof java.util.LinkedHashMap
【新运算符】
强制类型转换运算符as
assert 543667 as String == "543667"
assert 1234.compareTo("34749397" as int) < 0
assert 2 ** 3 == 8 //次方运算
return a<=>b //比较ab大小返回0,-1,1
空对象安全占位符?. ?:
if(obj?.value!=null)
//if(obj!=null&&obj.value!=null)
name=person.getName()?:"null"
//name=(person.getName()!=null)?person.getName():"null"
迭代操作符*.
List names=people*.name //对people迭代取name
直接域访问操作符.@
属性作用域默认private,并自动生成setter/getter,可覆写,当不想调用默认getter方法时使用
class User {
String name
User(String name) { this.name = name}
String getName() { "Name: $name" }
}
def user = new User('Bob')
assert user.name == 'Name: Bob' //getName()
assert user.@name == 'Bob'
方法指针操作符.&
如果想让方法a作为方法b的参数则可以将方法a当成一个闭包作为方法b的参数
def list = ['a','b','c']
//常规写法
list.each{
println it
}
//方法指针操作符写法
String printName(name){
println name
}
list.each(this.&printName)
【闭包】closure
匿名方法定义,可以赋予给一个变量名、作为参数传递给方法调用、或者被方法返回
闭包的语法{ < arguments> -> < body> }
当没有参数传入时,仍然需要保留箭头的存在{-> ... }
只有一个参数的闭包,可以不传入参数,运行时隐式的传入null参数
List fruit = [ "apple", "Orange", "Avocado", "pear", "cherry" ]
fruit.sort { String a, String b -> a.compareToIgnoreCase(b) }
println "Sorted fruit: ${fruit}"
可以将闭包赋予一个变量
Closure comparator = { String a, String b -> a.compareToIgnoreCase(b) }
fruit.sort(comparator)
assert comparator("banana", "Lemon") < 0
只有一个参数传入时,可以省略箭头,隐式的创建一个it参数,引用当前对象
[ "apple", "pear", "cherry" ].each { println it }
当闭包是一个方法的最后一个参数时,可以写在圆括号外面
List list = [ 1, 3, 5, 6 ]
assert 15 == list.inject(0, { runningTotal, value -> runningTotal + value })
assert 15 == list.inject(0) { runningTotal, value -> runningTotal + value }
【动态编程】
运行期解析对象属性和方法,允许在运行时增加对象属性和方法,可能出现调用未定义方法的情况。
动态编程带来的危险:编译器不能检查到类型错误、方法或属性的错误调用
难以调试,使用“单步跳入(step into)”经常进入一些反射中,使用“运行到光标处(run to cursor)”代替
public void sortPeopleByGivenName(List< Person> personList) {
Collections.sort(personList, new Comparator< Person>() {
public int compare(Person p1, Person p2) {
return p1.getFamilyName().compareTo(p2.getFamilyName());
}
} ) ;
}
将一个String作为属性或方法名进行调用
def sortPeople(people, property) {
people.sort { p1, p2 -> p1."${property}" < => p2."${property}" }
}
Groovy JDK中的增强
def names = [ "Glen", "Peter", "Alice", "Graham", "Fiona" ]
names.each(closure)
names.find(closure)
def glen = personList.find { it.firstName == "Glen" }
assert [ 4, 5, 5, 6, 5 ] == names.collect { it.size() }
def sortedNames = names.sort { it.size() }
def sortedNames = names.sort {
name1, name2 -> name1.size() < => name2.size()
}
assert [ "Alice", "Fiona", "Glen", "Graham", "Peter"] == sortedNames
assert "Glen, Peter, Alice, Graham, Fiona" == names.join(", ")
【参考资料】
Groovy脚本基础全攻略
http://blog.youkuaiyun.com/yanbober/article/details/49047515