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

添加新评论