微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

1groovy学习笔记

groovy学习笔记

groovy是一门类似于java的语言,在java语言的基础上,它吸收了很多脚本的特性,比如python,ruby。跟java一样,每个groovy文件也是编译成class文件,在JVM上运行。但是相比java,groovy的表达方式会更为简便。最近通过http://groovy.zeroleaf.com/core-syntax.htmlhttp://docs.groovy-lang.org/next/html/documentation/来学习groovy。这2篇其实是差不多的,前一个是简单的中文版,是一些groovy的基础语法。后一个是英文原版。
我是一个IDE重度患者,所以选择使用IntelliJ来学习groovy。

环境配置

下载groovy库

下载安装 sdkman,执行下面命令,按照提示安装即可

$ curl -s http://get.sdkman.io | bash

使环境变量生效

$ source "$HOME/.sdkman/bin/sdkman-init.sh"

安装 Groovy

$ sdk install groovy

此时可以查看groovy版本

192:~ fish$ groovy -v
Groovy Version: 2.4.7 JVM: 1.7.0_79 vendor: Oracle Corporation OS: Mac OS X

OK,groovy安装成功

配置IntelliJ

IntelliJ安装的时候认就会装上groovy插件,我们只要配置下project sdk和groovy library就好了

1、把groovy库从.sdkman复制出来,放到另一个目录。我是把groovy文件夹从/Users/fish/.sdkman/candidates/拷贝到/Users/fish/Documents/。
(因为.sdkman是隐藏文件,所以选择groovy library的时候没办法点到,所以我才把它拷贝出来,这1步应该可以省略的,希望)

2、点击new project,在左边列表选择groovy,右边project sdk选择jdk 1.8,groovy Library点击Create,然后选择/Users/fish/Documents/groovy/2.4.7,结果如下所示

3、点击next 就可以了创建一个空的groovy工程了
4、在src下new->groovy script,创建一个groovy脚本,在里面输入

printf "aaa"

点击右键run就可以看到控制台上输出了aaa。
至此,groovy环境配置完成,以后就可以用IntelliJ来开发groovy工程了。
好了,可以开始groovy学习之旅了

标识符

普通标识符

标识符(identifiers)以字母,美元符号$ 或者下划线开始. 不能以数字开始,如下所示,注意定义一个变量要写def,不用写明变量类型,因为groovy是动态类型的语言。当然写明变量类型也可以,此时就不用写def了。

def name
def item3
def with_underscore
def $dollarstart
//定义了一个String
def sex="male"
//定义了一个Integer
def age=4
//定义了一个map
def map = [:]

引用标识符

引用标识符(quoted identifiers)位于点表达式(dotted expression)的点号之后.

  • 如下所示可以用map.'a',来访问map的值,这就是引用标识符
  • 这里a的引号也可以不用写,map.a,结果是一样的。
  • 但是如果像L12不写引号的话,就是语法错误,必须加上引号,因为里面有空格
//定义一个map
def map = [:]
map."an identifier with a_3_2 space and double quotes" = "ALLOWED"
map.'with-dash-signs-and-single-quotes' = "ALLOWED"
map.'a'='b'

assert map.'a'=='b'
assert map.a=='b'

//语法错误
//assert map.an identifier with a_3_2 space and double quotes == "ALLOWED"
assert map."an identifier with a_3_2 space and double quotes" == "ALLOWED"
assert map.'with-dash-signs-and-single-quotes' == "ALLOWED"

groovy 字符串

字符串形式

首先来看下groovy字符串的表现形式,字符串表示的形式多种多样,如下所示

def map = [:]
map.'dollar slashy string'="dollar"
//如下类型字符串作为引用标识符都是对的
map.'single quote'
map."double quote"
map.'''triple single quote'''
map."""triple double quote"""
map./slashy string/
assert map.$/dollar slashy string/$=="dollar"

//稍微特殊的GString,也是对的
def firstname = "Homer"
map."Simson-${firstname}" = "Homer Simson"

assert map.'Simson-Homer' == "Homer Simson"

Groovy有java.lang.String和groovy.lang.GString两中字符串对象类型
单引号和三单引号字符串都是String,不支持插值.
双引号字和三双引号符串在没有插入表达式(interpolated expression)的情况下双引号字符串为 java.lang.String; 如果有,则为 groovy.lang.GString
当创建如下的字符串:

def startingAndEndingWithANewline = '''
line one
line two
line three
'''
assert strippedFirstNewline.startsWith('\n')

字符串插值

字符串插值,可以用${}进行插值,如下所示

def name = 'Guillaume' // a_3_2 plain string
def greeting = "Hello ${name}"
//plain
def greeting2 = "Hello${'girl'}"

assert greeting.toString() == 'Hello Guillaume'
println(greeting)
println(greeting2)

GString toString

一个方法(不管是在 Java 还是在 Groovy 中实现)期望一个java.lang.String,但我们传入一个 groovy.lang.GString 实例时,GString 的 toString() 方法自动,透明地被调用.

String takeString(String message) {
    assert message instanceof String
    return message
}

def message = "The message is ${'hello'}"
assert message instanceof GString

def result = takeString(message)
assert result instanceof String
assert result == 'The message is hello'

GString 和 String 的哈希码

尽管插值字符串可以用来代替普通 Java 字符串,但它们与普通字符串在某一方面还是有区别的: 即它们的哈希码(hashCodes)是不一样的. 普通 Java字符串是不可变的,然而 GString 的结果字符串 表示是可变的,取决于它的插入值. 即使结果字符串相同,GString 和 String 还是有不同的哈希码.

//左边是插值字符串,右边是普通字符串,hashcode不一致
assert "one: ${1}".hashCode() != "one: 1".hashCode()

def key = "a"
def m = ["${key}": "letter ${key}"]

assert m["a"] == null

backslash

你会发现结果字符串的第一个字符是一个换行符. 可以用反斜杠(backslash)转义换行符来移除该字符:

def strippedFirstNewline = '''\ line one line two line three '''
assert !strippedFirstNewline.startsWith('\n')

unicode

groovy还可以支持unicode字符,如下所示

//欧元货币符号
def a='The Euro currency symbol: \u20AC'
printf(a)

结果The Euro currency symbol: €

字符

与 Java 不同,Groovy 没有明确的字符字面量. 但是,你可以通过 3 种不同的方式明确的将 Groovy 字符串转换为字符:

char c1 = 'A'
assert c1 instanceof Character

def c2 = 'B' as char
assert c2 instanceof Character

def c3 = (char)'C'
assert c3 instanceof Character

List

groovy的List本质是java.util.List,但是跟java有些区别,主要是改了下,让使用更方便。

  • 创建的时候却像java的数组一样写 比如 下边的numbers不是一个数组,而是一个List(其实是ArrayList).
  • List元素访问可以直接用[]访问List的元素,在java里必须用get()方法,方便了不少,比如L6.
  • List元素访问可以从后往前,如L7,这个有点像python
  • List增加一个元素可以用<<这个操作符
//定义了一个List
def numbers = [1,2,3]         

assert numbers instanceof List  
assert numbers.size() == 3 
assert numbers[2] == 3
assert numbers[-1] == 3
//add
letters << 'e'

groovy的List可以放不同类型的东西,比如下边的List放了个int,一个String,一个boolean值

def heterogeneous = [1,"a",true]

数组Array

数组必须指明数据类型,访问数组元素的方法依然是[],和List一致。

String[] arrStr = ['Ananas','Banana','Kiwi']

assert arrStr instanceof String[]
assert !(arrStr instanceof List)

def numArr = [1,3] as int[]

assert numArr instanceof int[]
assert numArr.size() == 3
assert arrStr[2]=='Kiwi'

map

map实际数据类型是LinkedHashMap,但是创建访问有点像python的dictionary。

  • 创建的时候可以用[]
  • 访问的时候可以用[]或者.
  • 创建时key可以放常量也可以放变量,很有意思,变量用()包含起来
def colors = [red: '#FF0000',green: '#00FF00',blue: '#0000FF']   

assert colors['red'] == '#FF0000'    
assert colors.green  == '#00FF00'    

colors['pink'] = '#FF00FF'           
colors.yellow  = '#FFFF00'           

assert colors.pink == '#FF00FF'
assert colors['yellow'] == '#FFFF00'

assert colors instanceof java.util.LinkedHashMap

如下所示,上半段代码person里的,key是字符串“ff”,下半段代码里key是ff变量,即“name”字符串。

def ff = 'name'
def person = [ff: 'Guillaume']
assert !person.containsKey('name')
assert person.containsKey('ff')

person = [(ff): 'Guillaume']
assert person.containsKey('name')
assert !person.containsKey('ff')

数值

groovy会根据数值的大小自动分配数据类型,

//正数
def a = 1
assert a instanceof Integer

// Integer.MAX_VALUE
def b = 2147483647
assert b instanceof Integer

// Integer.MAX_VALUE + 1
def c = 2147483648
assert c instanceof Long

// Long.MAX_VALUE
def d = 9223372036854775807
assert d instanceof Long

// Long.MAX_VALUE + 1
def e = 9223372036854775808
assert e instanceof BigInteger

//负数
def na = -1
assert na instanceof Integer

// Integer.MIN_VALUE
def nb = -2147483648
assert nb instanceof Integer

// Integer.MIN_VALUE - 1
def nc = -2147483649
assert nc instanceof Long

// Long.MIN_VALUE
def nd = -9223372036854775808
assert nd instanceof Long

// Long.MIN_VALUE - 1
def ne = -9223372036854775809
assert ne instanceof BigInteger

String->boolean

String可以直接拿来当boolean值使用,空字符串相当于false,非空字符串相当于true.这里实际上隐式调用了asBoolean方法,转换成了boolean,这种隐式转换非常有意义,后面会看到。

assert (!'foo')   == false                      
assert (!'')      == true

三元运算符

来玩一个代码简化的游戏

if (string!=null && string.length()>0) {
    result = 'Found'
} else {
    result = 'Not found'
}

上边这段代码可以用三元运算符来简化

result = (string!=null && string.length()>0)?'Found':'Not found'

实际上利用string的boolean转化,我们还可以更简单,如下所示,其实上面的代码我在java里写过无数次,如果能直接用 string?'Found':'Not found'来表示真的方便了很多,希望java也能引入类似的语法

result = string?'Found':'Not found'

三元简化

我们经常写如下代码,可以看到重复写了user.name

displayName = user.name ? user.name : 'Anonymous'
groovy想了个办法来简化,可以如下表示

displayName = user.name ?: 'Anonymous'

特殊操作符

空指针保护?

首先有个groovy类Person,然后看下边的代码

class Person {
    /** 姓名 */
    String name

    /** * 为特定的人创建一个问候方法. * * @param otherPerson 待问候的人 * @return 问候信息 */
    String greet(String otherPerson) {
        "Hello ${otherPerson}"
    }
}
Person[] arrStr = [new Person(),new Person(),null]
def person = arrStr[2]
def name = person.name
assert name == null

这里person会是null,那么person.name就肯定会触发空指针,groovy定义了一种操作符可以避免空指针,那就是加一个?代码如下所示,这么写代码就方便多了,不用写那么多空判断,但是带来的隐患就是,最后出了问题,难以排查出原因,不好查哪里是null的源头。

//b1.groovy
/** * 空指针保护 * Created by fish on 17/1/7. */
Person[] arrStr = [new Person(),null]
def person = arrStr[2]
def name = person?.name
assert name == null

直接获取成员变量@

groovy获取成员变量,会直接调get方法,比如下边user.name会调用User的getName方法,我们这里name是Bob,但是我们复写了getName,所以getName得到Name: Bob,那如果我们想要的是Bob,怎么办呢?groovy提供了一种方法,加个@

//b2.groovy
class User {
    String name
    User(String name) { this.name = name}
    String getName() { "Name: $name" }
}
def user = new User('Bob')
assert user.name == 'Name: Bob'

直接获取成员变量的代码如下

assert user.@name == 'Bob'

函数

groovy的函数定义一般都是用def定义,形参不需要写明类型,结束的时候用return返回,return可省略

def f(a) {
    a * a;
}

def f(a,b) {
    a * b;
}

assert f(10) == 100
assert f(5,10) == 50
  • 如果使用void关键字代替def关键字定义函数,则函数的返回值将为null
  • 函数不能访问在外部通过def定义的变量:

函数和map

def f(a,b){
    return b+a.x+a.y;
}
//a=x:2,y:3 b=1
println f(x:2,1,y:3);//输出6
println f(x:2,y:3,1);//输出6

groovy的类可以不用写构造函数,而在new的时候指明就可以了。

class Car {
    String make
    String model
}

Car car = new Car(make: 'Peugeot',model: '508')
assert car.make == 'Peugeot'

ref

http://docs.groovy-lang.org/next/html/documentation/
http://groovy.zeroleaf.com/core-syntax.html
http://groovy.zeroleaf.com

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐