1groovy学习笔记

来源:互联网 发布:unity3d和php开发网站 编辑:程序博客网 时间:2024/04/29 04:10

groovy学习笔记

groovy是一门类似于java的语言,在java语言的基础上,它吸收了很多脚本的特性,比如python,ruby。跟java一样,每个groovy文件也是编译成class文件,在JVM上运行。但是相比java,groovy的表达方式会更为简便。最近通过http://groovy.zeroleaf.com/core-syntax.html和http://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 -vGroovy 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 namedef item3def with_underscoredef $dollarStart//定义了一个Stringdef sex="male"//定义了一个Integerdef age=4//定义了一个mapdef map = [:]

引用标识符

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

  • 如下所示可以用map.'a',来访问map的值,这就是引用标识符
  • 这里a的引号也可以不用写,map.a,结果是一样的。
  • 但是如果像L12不写引号的话,就是语法错误,必须加上引号,因为里面有空格
//定义一个mapdef 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 oneline twoline three'''assert strippedFirstNewline.startsWith('\n')

字符串插值

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

def name = 'Guillaume' // a_3_2 plain stringdef greeting = "Hello ${name}"//plaindef 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 GStringdef result = takeString(message)assert result instanceof Stringassert 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 oneline twoline 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 Characterdef c2 = 'B' as charassert c2 instanceof Characterdef 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增加一个元素可以用<<这个操作符
//定义了一个Listdef numbers = [1, 2, 3]         assert numbers instanceof List  assert numbers.size() == 3 assert numbers[2] == 3assert numbers[-1] == 3//addletters << '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, 2, 3] as int[]assert numArr instanceof int[]assert numArr.size() == 3assert 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 = 1assert a instanceof Integer// Integer.MAX_VALUEdef b = 2147483647assert b instanceof Integer// Integer.MAX_VALUE + 1def c = 2147483648assert c instanceof Long// Long.MAX_VALUEdef d = 9223372036854775807assert d instanceof Long// Long.MAX_VALUE + 1def e = 9223372036854775808assert e instanceof BigInteger//负数def na = -1assert na instanceof Integer// Integer.MIN_VALUEdef nb = -2147483648assert nb instanceof Integer// Integer.MIN_VALUE - 1def nc = -2147483649assert nc instanceof Long// Long.MIN_VALUEdef nd = -9223372036854775808assert nd instanceof Long// Long.MIN_VALUE - 1def ne = -9223372036854775809assert 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.nameassert name == null

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

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

直接获取成员变量@

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

//b2.groovyclass 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) == 100assert 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=1println f(x:2,1,y:3);//输出6println 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

0 0
原创粉丝点击