Groovy 简介

Groovy 是 Apache 旗下的一门基于 JVM 平台的动态编程语言,在语言的设计上 Groovy 吸纳了 Python、Ruby 和 Smalltalk 语言的优秀特性,语法非常简练和优美,开发效率也非常高。Groovy 可以与 Java 语言无缝对接,Groovy 脚本里可以写 Java 代码,也可以在 Java 程序里调用 Groovy 脚本,两者的无缝衔接有效地降低了 Java 开发者学习 Groovy 的成本。Groovy 代码能够与Java 代码很好地结合,Groovy 支持99%的 Java 语法,但是 Groovy 并不会替代 Java,而是相辅相成、互补的关系,具体使用哪门语言这取决于要解决的问题和使用的场景。

Groovy 是 用于 Java 虚拟机的一种敏捷的动态语言,它是一种成熟的面向对象编程语言,既可以用于面向对象编程,又可以用作纯粹的脚本语言。使用该种语言不必编写过多的代码,同时又具有闭包和动态语言中的其他特性。在Java中要输出"hello world"需要像下面这样,创建一个类,然后创建一个main方法:

  • public class Hello {
  • public static void main(String[] args) {
  • System.out.println("hello world");
  • }
  • }

在Groovy中,这些都可以省略,下面这4种方式都可以输出“hello world”。

  • System.out.println("hello world");
  • System.out.println "hello world";
  • println("hello world")
  • println 'hello world'

如果 Groovy 脚本文件里只有执行代码,没有类的定义,则 Groovy 编译器会生成一个 Script 的子类,类名和脚本文件的文件名一样,而脚本中的代码会被包含在一个名为run的方法中,同时还会生成一个main方法,作为整个脚本的入口。所以,作为 JVM 平台语言,与 Java 本质上还是一样的。

下面介绍一下一些通用的Groovy语法。

1、不需要分号

学过C/C++/java的同学都会对分号很熟悉,我们使用的如此频繁,几乎放在每一行的末尾,然而在Groovy中分号是可选的,你可以省略他们。

2、return关键字可省略

在 Groovy 中,方法的最后一句表达式可作为返回值返回,而不需要return关键字。

  • String sayHello() { return "hello world!" }
  • String sayHello() { "hello world!" }

3、def 和 类型

作为动态语言,Groovy 中所有的变量都是对象,所有对象继承自java.lang.Object。在声明一个变量时,Groovy 不要求强制类型声明,仅仅要求变量名前使用关键字 def(在 Groovy 1 以前的版本中,甚至连 def 都不需要)。

  • def var="hello world"
  • println var
  • println var.class

由此可以看到程序最后输出了var的实际类型为:java.lang.String

备注:作为例外,方法参数和循环变量的声明不需要def。

4、数组初始化语法

在 Groovy 中,{...} 语句块是留给闭包(Closure)使用的,所以不能像 Java 中一样使用下面这种方式初始化数组:

  • int[] array = { 1, 2, 3}

而应该是下面这样

  • int[] array = [1,2,3]

5、Getters and Setters

Groovy 默认会隐式的创建getter、setter方法,并且会提供带参的构造器,下面两者是等价的。

  • // In Java
  • public class Person {
  • private String name;
  • Person(String name) {
  • this.name = name
  • }
  • public String getName() {
  • return name
  • }
  • public void setName(String name) {
  • this.name = name
  • }
  • }
  • // In Groovy
  • class Person {
  • String name
  • }
  • def person = new Person(name: '张三')
  • assert '张三' == person.name
  • person.name = '李四'
  • //person.setName('李四')
  • assert '李四' == person.getName()

备注:当你对getter/setter方法有特殊要求,你尽可提供自己的方法,Groovy默认的getter/setter方法会被替换。

6、包访问权限

在 Java 中如果没有显式的指定访问修饰符(public、protected、private)那么默认是包访问权限,但在 Groovy 中默认是public的,所以需要使用@PackageScope注解。

  • class Person {
  • @PackageScope String name
  • }

7、使用命名的参数初始化Bean

  • class Student {
  • String name
  • int age
  • }

初始化一个实例的时候你可能会这样写:

  • def student = new Student()
  • student.name = "Tom"
  • student.age = 20

其实你可以用带命名的参数的默认构造器,会大大减少代码量:

  • def student = new Student(name: "Tom", age: 20)

8、使用with()来重复某一个操作

当更新一个实例的时候,你可以使用with()来省略相同的前缀,在Java中你必须这样写:

  • server.name = application.name
  • server.status = status
  • server.sessionCount = 3
  • server.start()
  • server.stop()

Groovy中则可以使用with():

  • server.with {
  • name = application.name
  • status = status
  • sessionCount = 3
  • start()
  • stop()
  • }

9、Equals 和 ==

Java里的==等同于Groovy里的is()方法,Groovy中的==是更智能的equals(),比较两个类的时候,你应该使用a.is(b),而不是==。Groovy中的==可以自动避免NullPointerException异常,如下所示:

替换

  • status != null && status.equals(ControlConstants.STATUS_COMPLETED)

  • status == ControlConstants.STATUS_COMPLETED

10、字符串

在Groovy种有两种字符串类型,普通字符串(java.lang.String)和插值字符串(groovy.lang.GString)。

普通字符串使用单引号

  • println 'hello'

插值字符串使用双引号

  • def name = '张三'
  • println "hello $name"

除此之外,还支持三单引号的写法,可以保留文本的换行及缩进格式

  • def lines = '''line one
  • line two
  • line three
  • '''
  • println lines
  • // 可以写成下面这种形式,可读性更好,\表示连字符
  • def lines = '''\
  • line one
  • line two
  • line three
  • '''
  • println lines

11、函数

Groovy 函数的返回类型可以不声明,默认返回最后一行代码的运行结果,但需要在声明函数的时候添加def关键字。反之,如果在声明函数中定义了返回值类型则可以省略def关键字,但函数中则必须使用return返回正确的数据类型。如下所示:

(1)函数定义时,参数的类型也可以不指定。例如:

  • //无需指定参数类型
  • String myFunction(arg1,arg2){
  • ...
  • }

(2)除了变量定义可以不指定类型外,Groovy中函数的返回值也可以是无类型的。比如:

  • //无类型的函数定义,必须使用def关键字
  • def myFunction(){
  • //最后一行代码的执行结果就是本函数的返回值
  • last_line
  • }
  • //如果指定了函数返回类型,则可不必加def关键字来定义函数,但是必须有return。
  • String getString(){
  • return "I am a string"
  • }

注意,如果函数定义时候指明了返回值类型的话,函数中则必须返回正确的数据类型,否则运行时报错。如果使用了动态类型的话,你就可以返回任何类型了。

Groovy 方法的其他特性与Java一样,比如支持重载、不定长参数(...)等。

12、闭包

Groovy 提供了闭包的支持,语法和 Lambda 表达式有些类似,简单来说,闭包就是一段可执行的代码块或函数指针。闭包在 Groovy 中是groovy.lang.Closure类的实例,这使得闭包可以赋值给变量,或者作为参数传递。Groovy 定义闭包的语法很简单,就像下面这样。

  • //闭包的参数为可选项
  • def closure = { [closureParameters -> ] statements }

闭包可以访问外部变量,而方法(函数)则不能。

  • def str = 'hello'
  • def closure={
  • println str
  • }
  • closure()//输出hello

闭包调用的方式有两种,闭包.call(参数)或者闭包(参数),在调用的时候可以省略圆括号。

  • def closure = {
  • param -> println param
  • }
  • closure('hello')
  • closure.call('hello')
  • closure 'hello'

闭包的参数是可选的,如果没有参数的话可以省略->操作符。

  • def closure = {println 'hello'}
  • closure()

多个参数以逗号分隔,参数类型和方法一样可以显式声明也可省略,如下所示:

  • def closure = { String x, int y ->
  • println "hey ${x} the value is ${y}"
  • }

如果只有一个参数的话,也可省略参数的定义,Groovy提供了一个隐式的参数it来替代它。

  • def closure = { it -> println it }
  • //和上面是等价的
  • def closure = { println it }
  • closure('hello')

闭包可以作为参数传入,闭包作为方法的唯一参数或最后一个参数时可省略括号。

  • def eachLine(lines, closure) {
  • for (String line : lines) {
  • closure(line)
  • }
  • }
  • eachLine('a'..'z',{ println it })
  • //可省略括号,与上面等价
  • eachLine('a'..'z') { println it }

标签: none

添加新评论