0 引言
最近发现测试同学在用groovy,感觉很好奇就看看,结果了解了一下,发现groovy可以用在Java项目中,而且不用担心兼容问题。
JVM的上游集合程序运行原理如下所示:
随便什么语言,反正JVM只认字节码文件,只要你的程序能够编译成JVM认识的字节码文件就行了。
后面打算在写一些Java程序的时候,适当的引进groovy,反正两者是兼容的,而且用groovy可以节省很大一部分代码量。
1 语法特性
1.0 输出
Java控制台输出语法:System.out.println()
Groovy控制台输出语法: println() 即可
1.2 语句
Java 在行代码结束后,或者说在每句话结束后,都需要加分号";"。但是Groovy不需要,加不加都行,groovy会自行的推断语句是否结束。
// Java 表达方式
public int a = 1;
// groovy 表达方式,两种都支持,会自行推断
public int a = 1
public int a = 1;
1.3 运算符
Java所有的运算符号groovy都支持,例如加等运算 +=之类的。
Groovy在原有Java支持的运算符上做了扩展,提供一个我特别想在Java身上看到的特性,范围。
groovy的范围用两个点表示,例如:1…10,表示1到10的整形数字,包含1和10。
同时范围运算符可以配合 in 关键字使用,例如 boolean a = 1 in 1…10 // true
def ints = 1..10
println ints // 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
println 5 in ints // 输出:true
1.4 定义变量 & 方法
Java所支持的方法定义,groovy全部支持。但就局部语法做了优化,使groovy更加开放。如果不知道,或者不确定方法的返回类型,可以用 def 来代替返回类型,进行方法定义。【Tip:groovy 还做了 对象 property 的扩展,但这个玩意本人认为这玩意还是少用为好。如果读者想了解这一方面的知识,请自行百度。】
// java 方式
// 变量
String s1 = "123";
// 方法
public String fun1(String r1){
...
}
// groovy 方式,以下两种方式都支持,def 代表定义的意思,至于方法返回什么类型,Groovy解释器会对其进行类型推断。
// 变量
def s1 = "123"
String s1 = "123"
// 方法
String fun1(String r1){
...
}
def fun1(String r1){
...
}
1.5 类
对于Java而言,所有的POJO属性默认都是**“缺省类型”**,只能同包可见。而大多Java开发工作者,都会给POJO的属性加上 private修饰符,表示该属性只能此类访问。但对于groovy开发者而言,无需加上private修饰符,因为其属性默认就是用private修饰的。
Tip: Kotlin有个好玩的特性,就是对于类属性可以用 set 和 get 标记,等同于 Java POJO 中的 getter 和 setter 方法。
1.6 NPE判断
Java 对于 NPE 是深恶痛绝,Java 工作者想出了各种办法,例如 Objects.requireNonNull(obj),groovy可以用问号“❓”解决这个问题。如下:
// java 方式
Objects.requireNonNull(obj)
// groovy 可以用问号代替 NPE 判断
obj?.find {}
1.7 模版字符串
def name = "Groovy"
def temp = "This is ${name}"
// 使用方式就是 ${var}
println temp // This is Groovy
// 还可以做表达式
def temp2 = "This Tutorial is about ${name + "123"}"
println temp // This is Groovy123
2 集合特性
2.0 定义列表
Java 通常需要用 new ArrayList<>() 这种方式去定义列表,而 groovy 定义列表就很好玩了。具体看代码:
// 定义列表,java 可以这样定义 Lists.of(1,2,3,4)
def ints = [1,2,3,4]
// 添加元素,Java 可以这样添加 ints.add(5)
ints.add(5)
ints << 5 // 骚吧,好玩吧
// 删除元素,Java 这样 ints.remove(4)
ints.remove(2)
// 读取元素,ints.get(2)
ints.get(3)
ints[3] // 读取最后一个元素的骚操作:ints[-1]
// 拼接元素, Java 这样 ints.addAll(list)
def list = [5,6,7]
ints += list
ints << list
// 去除元素,Java 这样 ints.munit(list)
def list = [1,2]
ints -= list
// 遍历列表,Java 这样 ints.foeEach(item -> {}) 或者 for-in
for(def i in ints) {...}
ints.each({it -> ...}) //这是闭包,后面会讲
// 查元素,Java 这样 ints.stream().find(Option)
ints.find({it -> ...}) // 返回第一个发现的元素
ints.findAll({it -> ...}) // 返回所有符合条件的元素
// 其它
ints.join(",")// 用特殊字符串拼接列表,输出 "1,2,3,4"
ints.count(4)// 计数,输出1
ints.sort() // 排序,输出[1,2,3,4]
3 映射特性
Java定义映射可以用new HashMap<String, String>(),Groovy定义映射就很简单,如下:
def map = [
"k1": "v1",
"k2": "v2",
"k3": "v3"
]
println map // [k1:v1, k2:v2, k3:v3]
map."k4" = "v4" // 知道名字的
def k4 = "k4"
map[k4] = "v4" // 不知道名字的
println map // [k1:v1, k2:v2, k3:v3, k4:v4]
Tip: Java支持的,groovy都支持
4 闭包
groovy中的闭包相当于Java中的lambda,但是写法上有所差异,具体如下:
// java 的 lambda
(args...) -> {}
// groovy 中的 Closure(闭包)
{ args -> }
两个都是在大括号下写的,Java的参数需要用小括号包裹(一个参数可以省略),执行体用大括号包裹。但是如果是groovy的话,其闭包都是在大括号中,对于一个参数的话,groovy可以省略不写,直接用 it 关键字代替那个默认的参数。如下:
// java 的 lambda 对 for-each 支持
List<String> list = ["1234","1245","23446"]
// Java
list.forEach(item -> {
System.out.println(item);
})
// groovy
list.forEach({ item ->
System.out.println(item);
})
list.forEach({
System.out.println(it); // it 为默认参数,等价于item
})
好了,知道怎么用就行了,多余的边写边百度呗!
番外1:Java 与 groovy 混合开发【maven项目】
step1: 添加 groovy 依赖
<!-- groovy 支持 -->
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
</dependency>
tip: 不需要指定版本信息,spring boot 中部分源码也是用 groovy 开发的,本身有 groovy 的父集。
step2: 添加 groovy 编译插件
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>1.13.1</version>
<executions>
<execution>
<goals>
<goal>addSources</goal>
<goal>addTestSources</goal>
<goal>generateStubs</goal>
<goal>compile</goal>
<goal>generateTestStubs</goal>
<goal>compileTests</goal>
<goal>removeStubs</goal>
<goal>removeTestStubs</goal>
</goals>
</execution>
</executions>
</plugin>
tip:groovy 编译插件会和 maven 的生命周期进行绑定,而且 groovy 插件扫描的不是 Java 目录下的源代码,而是 groovy 下的源代码
step3: 创建与 Java 同级别的源码目录
tip1: 如果是 spring boot 开发,groovy 的包应该低于启动程序(含main方法的那个类)包级别。