概述 为了进一步兼容Java,我们Groovy核心团队决定从Groovy 4.0.0开始支持Switch Expression、Record Class、Sealed Class等Java语言特性。值得注意的是,即使Groovy 4.0.0运行在Java 8上,这些新特性依然可以使用。除了兼容Java语言特性外,Groovy自身也新增了不少实用的新特性,比如增强Range、支持TOML、Java化(@POJO
)、GINQ(Groovy-Integrated Query)等。
新特性预览 Switch Expression 使用->
表示各个逻辑分支
def i = 1 def result = switch (i) { case 0 -> 'zero' case 1 -> 'one' case 2 -> 'two' default -> throw new IllegalStateException('unknown number' ) } assert 'one' == result
使用花括号{...}
处理较为复杂逻辑分支
def i = 3 def result = switch (i) { case 0 -> 'zero' case 1 -> 'one' case 2 -> 'two' case 3 -> { def p1 = 'th' def p2 = 'ree' "${p1}${p2}" } default -> throw new IllegalStateException('unknown number' ) } assert 'three' == result
使用yield
来产生switch expression的结果值
def lang = 'CN' def i = 3 def result = switch (i) { case 0 -> 'zero' case 1 -> 'one' case 2 -> 'two' case 3 -> { if ('CN' == lang) { yield '三' } yield 'three' } default -> throw new IllegalStateException('unknown number' ) } assert '三' == result
使用:
表示逻辑分支并使用yield
产生switch expression的结果值
def lang = 'EN' def i = 3 def result = switch (i) { case 0 : yield 'zero' case 1 : yield 'one' case 2 : yield 'two' case 3 : if ('CN' == lang) { yield '三' } yield 'three' default: throw new IllegalStateException('unknown number' ) } assert 'three' == result
使用:
复用逻辑分支
def i = 4 def result = switch (i) { case 0 : yield 'zero' case 1 : yield 'one' case 2 : yield 'two' case 3 : yield 'three' case 4 : case 5 : default: 'unknown number' } assert 'unknown number' == result
Record Class 使用record
关键字定义Record Class
record Person(String name, int age) { } def p = new Person('山风小子' , 37 )assert '山风小子' == p.name()assert 37 == p.age()
定义Compact constructor
record Person(String name, int age) { Person { if (age < 0 ) { throw new IllegalArgumentException("invalid age: ${age}" ) } name = name.toUpperCase() } } def p1 = new Person('Daniel' , 37 )assert 'DANIEL' == p1.name()try { def p2 = new Person('Unknown' , -1 ) assert false: 'Should never reach here' } catch (IllegalArgumentException e) { assert 'invalid age: -1' == e.message }
Sealed Class 使用sealed
定义Sealed Class,注:如果子类没有显式声明final
、sealed
或non-sealed
,那么默认non-sealed
sealed abstract class Shape permits Ellipse, Rectangle, Triangle { } non-sealed class Ellipse extends Shape { } class Circle extends Ellipse {} sealed class Rectangle extends Shape permits Square { } class Square extends Rectangle {} final class Triangle extends Shape {} assert new Ellipse() instanceof Shapeassert new Circle() instanceof Shapeassert new Rectangle() instanceof Shapeassert new Square() instanceof Shapeassert new Triangle() instanceof Shape
增强Range 新增<..
(左开右闭区间)以及<..<
(开区间)
assert [2 , 3 , 4 , 5 , 6 ] == 1 <..6 assert [2 , 3 , 4 , 5 ] == 1 <..<6 assert [1 , 2 , 3 , 4 , 5 ] == 1. .<6 assert [1 , 2 , 3 , 4 , 5 , 6 ] == 1. .6
支持TOML 解析TOMLdef ts = new groovy.toml.TomlSlurper()def toml = ts.parseText ''' # This is a TOML document. title = "TOML Example" [owner] name = "山风小子" [blog] domainName = "blog.sunlan.me" languages = ["CN", "EN"] ''' assert 'TOML Example' == toml.titleassert '山风小子' == toml.owner.nameassert 'blog.sunlan.me' == toml.blog.domainNameassert ['CN' , 'EN' ] == toml.blog.languages
创建TOML(暂不支持美化输出结果)def tb = new groovy.toml.TomlBuilder()tb { title 'TOML Example' owner { name '山风小子' } blog { domainName 'blog.sunlan.me' languages 'CN' , 'EN' } } assert '''\ title = 'TOML Example' owner.name = '山风小子' blog.domainName = 'blog.sunlan.me' blog.languages = ['CN', 'EN'] ''' == tb.toString()
Java化(@POJO
) Groovy编译出来的class依赖Groovy自带的类(比如:GroovyObject
),因此在运行Groovy程序时不得不将Groovy运行时jar文件都引入。而@POJO
与@CompileStatic
结合使用便可助我们“轻装上阵”,摆脱Groovy运行时jar文件,但有个大前提,Groovy程序本身没有用到Groovy自带的类,包括GString
。
@groovy .transform.CompileStatic@groovy .transform.stc.POJOclass HelloGroovy {}
编译后所生成的bytecode如下所示(注:Groovy的@Generated
不影响程序独立运行)
public class HelloGroovy { public <init>()V @Lgroovy /transform/Generated;() L0 ALOAD 0 INVOKESPECIAL java/lang/Object.<init> ()V L1 RETURN LOCALVARIABLE this LHelloGroovy; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 }
GINQ(Groovy-Integrated Query) 详见《Groovy 4之新特性GINQ预览 》
其他 详见Groovy 4.0.0 Release Notes
结束语 Groovy 4.0.0除了新增众多语言特性外,还修正了许多bug,尤其是静态编译那块。另外,Groovy 4.0.0也是唯一真正支持Java 17的版本,故一旦发布,强烈建议升级至该版本。
相关文章 《Back in the Groovy 4》