Groovy基于Java语言,兼容Java语法,他其实就是一种较为系统的java语法糖,既可以作为面向对象编程语言,也可以作为脚本语言。
基础语法
Groovy Script 和 Groovy Object
作为脚本时,Groovy脚本文件中的所有脚本命令将会生成一个Java Class,并继承groovy.lang.Script
类。
比如如下脚本 Hello.groovy
:
将会生成一个与脚本文件名称相同的类,这里是Hello.class
:
import groovy.lang.Binding;
import groovy.lang.Script;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.callsite.CallSite;
// 继承Script,并提供一个 main 方法
public class Demo01 extends Script {
public Demo01() {
CallSite[] var1 = $getCallSiteArray();
super();
}
public Demo01(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
}
public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].callStatic(InvokerHelper.class, Demo01.class, args);
}
public Object run() {
CallSite[] var1 = $getCallSiteArray();
return var1[1].callCurrent(this, "hello world");
}
}
不仅如此,在一个Groovy文件中可以混合类定义与脚本定义,但是脚本名不可以与脚本中定义的类名相同,因为脚本类也会生成Class,Class是不可以重名的。
如下代码是一个混合脚本,除了Hello.class
,还会生成一个Person.class
:
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import groovy.transform.Generated;
import groovy.transform.Internal;
import java.beans.Transient;
import org.codehaus.groovy.runtime.callsite.CallSite;
// Groovy 的class 默认实现 GroovyObject 接口
public class Person implements GroovyObject {
@Generated
public Person() {
CallSite[] var1 = $getCallSiteArray();
super();
MetaClass var2 = this.$getStaticMetaClass();
this.metaClass = var2;
}
@Generated
@Internal
@Transient
public MetaClass getMetaClass() {
MetaClass var10000 = this.metaClass;
if (var10000 != null) {
return var10000;
} else {
this.metaClass = this.$getStaticMetaClass();
return this.metaClass;
}
}
@Generated
@Internal
public void setMetaClass(MetaClass var1) {
this.metaClass = var1;
}
}
使用def定义变量
Groovy提供关键字def用于定义变量,他是一种动态类型机制,也就是说,在运行时才会去校验数据类型;而静态类型是在编译时对数据类型进行校验检查。
分号可以用换行替换
print("hello world")
print("hello world")
类、成员默认全是public的
Java类、以及类中的成员,默认修饰级别为default,而Groovy中默认则是public的:
上面两个代码是相同的。
类中的属性会自动添加getter和setter
class Person {
def name
def age
def hobby
}
def p = new Person()
println(p.getHobby())
对象的属性操作
// 创建对象
def p = new Person()
// 使用属性名直接给成员赋值
p.name = "张三"
p["age"] = 20
// 使用setter方法赋值
p.setHobby("打篮球")
// 使用属性名读取属性值
println(p.name)
println(p["age"])
// 使用getter方法获取
println(p.getHobby())
无论是哪儿种方式,实际上最终仍然是调用的getter和setter
创建对象使用构造器指定属性值
def p = new Person(name: "张三", age: 12)
方法的定义
声明方法时,参数类型可省略:
String getHelloStr(String name) {
return "hello " + name
}
println getHelloStr("张三")
// 方法的返回值与参数类型可以使用def代替
def getHelloStr1(def name) {
return "hello " + name
}
println getHelloStr1("张三")
// 方法的参数类型可以不写
def getHelloStr2(name) {
return "hello " + name
}
println getHelloStr2("张三")
// renturn 关键字可以省略
def getHelloStr3(name) {
"hello ${name}"
}
println getHelloStr3("张三")
方法的调用可以省略()
当不引起歧义的时候,方法调用的小括号可以省略,下面两行代码是相同的:
println "hello world"
println("hello world")
在Groovy中没有基本类型,字面量可以直接调用包装类型方法
def one = 1.longValue()
三种字符串表示
单引号:字符串常量,不具有运算能力,会被解析为 java.lang.String
双引号:可引用变量${}
,具有运算能力,会被解析为 GStringImpl
三引号:支持换行,会被解析为java.lang.String
def name = '张三'
def sayhello = "你好,${name}"
// 在不引起歧义的情况下可省略大括号
sayHello = "你好, $name";
def str = '''
多行字符串
支持换行
**不支持**引用变量 ${name}
'''
自动类型转换
在需要的时候,类型之间会自动发生类型转换。
控制语句
控制语句基本与java相同。
闭包
定义:开放的、匿名的代码块,他可以接收参数,也可以有返回值。闭包还可以引用其周围作用域中声明的变量。
语法:
{
[closureParameters ->] statements
}
使用闭包需要:
1. 将闭包赋值给一个变量
2. 使用 `变量名()` 或者 `变量名.call()` 调用闭包
> 开发中通常将闭包作为方法参数调用
示例:
```groovy
def helloWorld = {
println "hello world"
}
helloWorld()
def hello = {
name -> println "hello $name"
}
hello.call("张三")
def run(Closure closure) {
closure();
}
run({println("run!!!")})
def caculate(num1, num2, Closure closure) {
closure(num1, num2)
}
caculate(10, 15, {k, v -> println("$k + $v = ${k+v}")})
// 如果闭包方法的最后一个参数,那么调用时,可以将闭包这个参数写在方法外面
caculate(10, 15) {k, v -> println("$k + $v = ${k+v}")}