加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Groovy 脚本基础全攻略(上)

发布时间:2020-12-14 16:45:31 所属栏目:大数据 来源:网络整理
导读:(点击 上方公众号 ,可快速关注) 来源:工匠若水(@工匠若水) 链接:http://blog.csdn.net/yanbober/article/details/49047515 1 背景 Groovy脚本基于Java且拓展了Java,所以从某种程度来说掌握Java是学习Groovy的前提,故本文适用于不熟悉Groovy却想快速得

(点击上方公众号,可快速关注)


来源:工匠若水(@工匠若水)

链接:http://blog.csdn.net/yanbober/article/details/49047515


1 背景


Groovy脚本基于Java且拓展了Java,所以从某种程度来说掌握Java是学习Groovy的前提,故本文适用于不熟悉Groovy却想快速得到Groovy核心基础干货的Java开发者(注意是Java),因为我的目的不是深入学习Groovy语言,所以本文基本都是靠代码来解释,这样最直观,同时也够干货基础入门Groovy的特点和结构。


开始介绍前先给一个大法,《官方权威指南》英文好的可以直接略过本文后续内容,我需要的只是Groovy皮毛;再次向Groovy的标志致敬,左手一个Java,右手一个Groovy,不好意思,我技术水平太Low了(T–T__《琅琊榜》看多了!!!)。



Groovy是一种动态语言,它和Java类似(算是Java的升级版,但是又具备脚本语言的特点),都在Java虚拟机中运行。当运行Groovy脚本时它会先被编译成Java类字节码,然后通过JVM虚拟机执行这个Java字节码类。


快速安装指南:


安装Groovy在各种Bash下都是通用的,具体如下命令就可搞定:


$ curl -s get.sdkman.io | bash

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

$ sdk install groovy

$ groovy -version

//至此就可以享用了!


我们在写Groovy代码时可以直接使用自己喜欢的文本编辑器编辑OK以后以.groovy后缀保存,然后在终端执行如下命令即可运行:


$ groovy ./TestFile.groovy


或者我们可以通过groovyConsole来进行groovy代码开发运行(由于不需要特别深入学习使用Groovy,所以个人非常喜欢这种模式的开发运行),如下图:



再或者我们还可以使用Intellij IDEA等工具安装groovy插件进行groovy开发,这里不再一一叙述了(配置环境点我),直接给出一个读取指定文件内容打印的例子,如下:



OK,有了上面这些简单粗暴的基础和环境之后那我们快速开战吧。


2 语法基础


这里开始我们就来快速简单粗暴的了解一下Groovy语法,其实和Java类似,但也有些区别,下面我们一步一步来看吧,切记对比学习,这才是秘笈。


2-1 注释


Groovy的单行注释、多行注释、文档注释基本都和Java一样,没啥特殊的,不再细说。只有一种特殊的单行注释需要留意一下即可。如下:


#!/usr/bin/env groovy

println "Hello from the shebang line"


这种注释通常是用来给UNIX系统声明允许脚本运行的类型的,一般都是固定写法,没啥讲究的。


2-2 关键字


Groovy有如下一些关键字,我们些代码命名时要注意:


as、assert、break、case、catch、class、const、continue、def、default、do、else、enum、extends、false、finally、for、goto、if、implements、import、in、instanceof、interface、new、null、package、return、super、switch、this、throw、throws、trait、true、try、while


这玩意和其他语言一样,没啥特殊的,自行脑补。


2-3 标识符


对于Groovy的标示符和Java还是有些共同点和区别的,特别是引用标示符的区别,具体可以往下看。


2-3-1 普通标识符


普通标识符定义和C语言类似,只能以字母、美元符、下划线开始,不能以数字开头。如下例子:


//正确

def name

def $name

def name_type

def foo.assert

//错误

def 5type

def a+b


2-3-2 引用标识符


引用标识符出现在点后的表达式中,我们可以如下一样使用:


def map = [:]


//引用标示符中出现空格也是对的

map."an identifier with a space and double quotes" = "ALLOWED"

//引用标示符中出现横线也是对的

map.'with-dash-signs-and-single-quotes' = "ALLOWED"


assert map."an identifier with a space and double quotes" == "ALLOWED"

assert map.'with-dash-signs-and-single-quotes' == "ALLOWED"


当然了,Groovy的所有字符串都可以当作引用标示符定义,如下:


//如下类型字符串作为引用标识符都是对的

map.'single quote'

map."double quote"

map.'''triple single quote'''

map."""triple double quote"""

map./slashy string/

map.$/dollar slashy string/$


//稍微特殊的GString,也是对的

def firstname = "Homer"

map."Simson-${firstname}" = "Homer Simson"


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

2-4 字符及字符串


Groovy有java.lang.String和groovy.lang.GString两中字符串对象类型,具体如下细说。


2-4-1 单引号字符串


单引号字符串是java.lang.String类型的,不支持站位符插值操作,譬如:


def name = 'Test Groovy!'

def body = 'Test $name'


assert name == 'Test Groovy!'

assert body == 'Test $name' //不会替换$name站位符


Groovy的字符串可以通过”+“直接拼接,譬如:


assert 'ab' == 'a' + 'b'


其中涉及转义字符规则同Java,只用特殊注意”’“的转义即可。


2-4-2 三重单引号字符串


三重单引号字符串是java.lang.String类型的,不支持站位符插值操作,可以标示多行字符串,譬如:


def aMultilineString = '''line one

line two

line three'''


三重单引号字符串允许字符串的内容在多行出现,新的行被转换为“n”,其他所有的空白字符都被完整的按照文本原样保留;字符开头添加“/”表示字符内容不转义反斜杠“”,只有在反斜杠接下来是一个字符u的时候才需要进行转义,因为u表示一个unicode转义。如下:


def strippedFirstNewline = '''

line one

line two

line three

'''


assert !strippedFirstNewline.startsWith('n')


2-4-3 双引号字符串


双引号字符串支持站位插值操作,如果双引号字符串中不包含站位符则是java.lang.String类型的,如果双引号字符串中包含站位符则是groovy.lang.GString类型的。


对于插值占位符我们可以用${}或者$来标示,${}用于一般替代字串或者表达式,$主要用于A.B的形式中,具体如下例子:


def name = 'Guillaume' // a plain string

def greeting = "Hello ${name}"

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


def sum = "The sum of 2 and 3 equals ${2 + 3}"

assert sum.toString() == 'The sum of 2 and 3 equals 5'


def person = [name: 'Guillaume',age: 36]

assert "$person.name is $person.age years old" == 'Guillaume is 36 years old'


特别注意,$只对A.B等有效,如果表达式包含括号(像方法调用)、大括号、闭包等符号则是无效的。譬如:


def number = 3.14

shouldFail(MissingPropertyException) {

println "$number.toString()"

}


//该代码运行抛出groovy.lang.MissingPropertyException异常,因为Groovy认为去寻找number的名为toString的属性,所以异常


注意,在表达式中访问属性前必须保证属性已经定义好(值为空也可以),如果使用了未定义的属性会抛出groovy.lang.MissingPropertyException异常。 GString还支持延迟运算,譬如在GString中使用闭包,闭包在调用GString的toString()方法时被延迟执行;闭包中可以有0或1个参数,若指定一个参数,则参数会被传入一个Writer对象,我们可以利用这个Writer对象来写入字符,若没有参数,闭包返回值的toString()方法被调用。譬如:


//无参数闭包

def sParameterLessClosure = "1 + 2 == ${-> 3}"

assert sParameterLessClosure == '1 + 2 == 3'

//一个参数闭包

def sOneParamClosure = "1 + 2 == ${ w -> w << 3}"

assert sOneParamClosure == '1 + 2 == 3'


上面了解了GString的推迟运算特性,下面我们再来看一个牛逼的特性,如下:


def number = 1

def eagerGString = "value == ${number}"

def lazyGString = "value == ${ -> number }"


assert eagerGString == "value == 1"

assert lazyGString == "value == 1"


number = 2

assert lazyGString == "value == 2"


可以看见,eagerGString是普通的双引号插值站位替换,lazyGString是双引号闭包插值替换,我们可以发现在number变为2以后他们的运算结果就有了差异。可以明显推理到结论,一个普通插值表达式值替换实际是在GString创建的时刻,一个包含闭包的表达式由于延迟运算调运toString()方法,所以会产生一个新的字符串值。


当然了,GString和String即使字符串一样他们的HashCode也不会一样,譬如:


assert "one: ${1}".hashCode() != "one: 1".hashCode()


由于相同字符串的String与GString的HashCode不同,所以我们一定要避免使用GString作为MAP的key,譬如:


def key = "a"

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


assert m["a"] == null //由于key的HashCode不同,所以取不到


其中涉及转义字符规则同Java,只用特殊注意””“的转义即可。


2-4-4 多重双引号字符串


多重双引号字符串也支持站位插值操作,我们要特别注意在多重双引号字符串中的单引号和双引号转换问题。譬如:


def name = 'Groovy'

def template = """

Dear Mr ${name},


You're the winner of the lottery!


Yours sincerly,89);"> Dave

"""


assert template.toString().contains('Groovy')


2-4-5 斜线字符串


斜线字符串其实和双引号字符串很类似,通常用在正则表达式中,下面我们看几个例子,如下:


//普通使用

def fooPattern = /.*foo.*/

assert fooPattern == '.*foo.*'

//含转义字符使用

def escapeSlash = /The character / is a forward slash/

assert escapeSlash == 'The character / is a forward slash'

//多行支持

def multilineSlashy = /one

two

three/


assert multilineSlashy.contains('n')

//含站位符使用支持

def color = 'blue'

def interpolatedSlashy = /a ${color} car/


assert interpolatedSlashy == 'a blue car'


特别注意,一个空的斜线字符串会被Groovy解析器解析为一注释。


2-4-6 字符Characters


不像Java,Groovy没有明确的Characters。但是我们可以有如下三种不同的方式来将字符串作为字符处理,譬如:


char c1 = 'A'

assert c1 instanceof Character


def c2 = 'B' as char

assert c2 instanceof Character


def c3 = (char)'C'

assert c3 instanceof Character


2-5 数字Numbers


Groovy支持各种类型的整型和数值类型,通常支持Java支持的那些,下面我们仔细来说说。


2-5-1 整型


Groovy像Java一样支持如下一些整型,byte、char、short、int、long、java.lang.BigInteger。我们在使用中可以像下面例子一样:


// primitive types

byte b = 1

char c = 2

short s = 3

int i = 4

long l = 5


// infinite precision

BigInteger bi = 6


int xInt = 077

assert xInt == 63


int xInt = 0x77

assert xInt == 119


int xInt = 0b10101111

assert xInt == 175


2-5-2 浮点型


Groovy像Java一样支持如下一些浮点型,float、double、java.lang.BigDecimal。我们在使用中可以像下面例子一样:


float f = 1.234

double d = 2.345

BigDecimal bd = 3.456

assert 1e3 == 1_000.0

assert 2E4 == 20_000.0

assert 3e+1 == 30.0

assert 4E-2 == 0.04


2-6 Booleans类型


Boolean类型没啥解释的,和其他语言一样,就两个值,如下:



def myBooleanVariable = true

boolean untypedBooleanVar = false

booleanField = true


比较简单,没啥特例,自行脑补。


2-7 Lists类型


Groovy同样支持java.util.List类型,在Groovy中同样允许向列表中增加或者删除对象,允许在运行时改变列表的大小,保存在列表中的对象不受类型的限制;此外还可以通过超出列表范围的数来索引列表。如下例子:


//使用动态List

def numbers = [1,2,3]

assert numbers instanceof List

assert numbers.size() == 3

//List中存储任意类型

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

//判断List默认类型

def arrayList = [1,3]

assert arrayList instanceof java.util.ArrayList

//使用as强转类型

def linkedList = [2,3,4] as LinkedList

assert linkedList instanceof java.util.LinkedList

//定义指定类型List

LinkedList otherLinked = [3,4,5]

assert otherLinked instanceof java.util.LinkedList

//定义List使用

def letters = ['a','b','c','d']

//判断item值

assert letters[0] == 'a'

assert letters[1] == 'b'

//负数下标则从右向左index

assert letters[-1] == 'd'

assert letters[-2] == 'c'

//指定item赋值判断

letters[2] = 'C'

assert letters[2] == 'C'

//给List追加item

letters << 'e'

assert letters[ 4] == 'e'

assert letters[-1] == 'e'

//获取一段List子集

assert letters[1,3] == ['b','d']

assert letters[2..4] == ['C','d','e']

//多维List支持

def multi = [[0,1],[2,3]]

assert multi[1][0] == 2


2-8 Arrays类型


Groovy中数组和Java类似,具体如下:


//定义初始化String数组

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

assert arrStr instanceof String[]

assert !(arrStr instanceof List)

//使用def定义初始化int数组

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

assert numArr instanceof int[]

assert numArr.size() == 3

//声明定义多维数组指明宽度

def matrix3 = new Integer[3][3]

assert matrix3.size() == 3

//声明多维数组不指定宽度

Integer[][] matrix2

matrix2 = [[1,2],[3,4]]

assert matrix2 instanceof Integer[][]

//数组的元素使用及赋值操作

String[] names = ['Cédric','Guillaume','Jochen','Paul']

assert names[0] == 'Cédric'

names[2] = 'Blackdrag'

assert names[2] == 'Blackdrag'


2-9 Maps类型


Map是“键-值”对的集合,在Groovy中键key不一定是String,可以是任何对象(实际上Groovy中的Map就是java.util.Linke dHashMap)。如下:


//定义一个Map

def colors = [red: '#FF0000',green: '#00FF00',blue: '#0000FF']

//获取一些指定key的value进行判断操作

assert colors['red'] == '#FF0000'

assert colors.green == '#00FF00'

//给指定key的对赋值value操作与判断

colors['pink'] = '#FF00FF'

colors.yellow = '#FFFF00'

assert colors.pink == '#FF00FF'

assert colors['yellow'] == '#FFFF00'

//判断Map的类型

assert colors instanceof java.util.LinkedHashMap

//访问Map中不存在的key为null

assert colors.unknown == null

//定义key类型为数字的Map

def numbers = [1: 'one',2: 'two']

assert numbers[1] == 'one'


对于Map需要特别注意一种情况,如下:


//把一个定义的变量作为Map的key,访问Map的该key是失败的

def key = 'name'

def person = [key: 'Guillaume']

assert !person.containsKey('name')

assert person.containsKey('key')

//把一个定义的变量作为Map的key的正确写法---添加括弧,访问Map的该key是成功的

person = [(key): 'Guillaume']

assert person.containsKey('name')

assert !person.containsKey('key')


(文章超字数,请继续看多图文的下篇)




安卓应用频道

微信号:AndroidPD

打造东半球最好的 安卓技术 微信号

--------------------------------------

商务合作QQ:2302462408

投稿网址:top.jobbole.com




(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读