您的位置:首页 > 其它

Gradle基础之Groovy语法

2018-01-07 22:55 579 查看

Gradle基础之Groovy语法

在使用Android Studio开发app的过程中,都会接触到Gradle配置,而Gradle的配置是基于Grovvy语法的。因此,要想熟练的使用Gradle进行配置,就必须熟悉Groovy语法,下面开始讲解下Groovy的基本语法。

Groovy可以看作是java的加强版,扩展了java的语法,拥有自己的一些特性。

Groovy语法官方文档

1. 注释

1.1 单行注释

单行注释如下所示,跟java一样:

// a standalone single line comment
println "hello" // a comment till the end of the line


1.2 多行注释

多行注释如下所示,跟java一样:

/* a standalone multiline comment
spanning two lines */
println "hello" /* a multiline comment starting
at the end of a statement */
println 1 /* one */ + 2 /* two */


1.3 GroovyDoc 注释

GroovyDoc跟javaDoc语法也是一样的,如下所示:

/**
* A Class description
*/
class Person {
/** the name of the person */
String name

/**
* Creates a greeting method for a certain person.
*
* @param otherPerson the person to greet
* @return a greeting message
*/
String greet(String otherPerson) {
"Hello ${otherPerson}"
}
}


1.4 Shebang line

除了单行注释,还有一种特殊的单行注释,如下所示,叫做Shebang line(各位可以自行去翻译)。这行注释主要是便于unix理解,有了这行注释就可以直接在命令行运行groovy脚本文件啦。当然前提是电脑上要安装了Groovy,且要把Groovy加入path环境变量,注意这种注释中#必须是第一个字符,否则会报编译错误。

#!/usr/bin/env groovy
println "Hello from the shebang line"


2. Groovy关键字

Groovy语法的关键字如下所示:

asassertbreakfinallyimplementsnewswitchtrait
casecatchclassfalseimportnull符号switchtrue
constcontinuedefforinpackagethistry
defaultdoelsegotoinstanceofreturnthrowwhile
enumenumextendsifinterfacesuperthrows

3. 标识符

3.1 正常的标识符

标识符可以由字母、美元符号以及下划线开头,不能以数字开头。

字符的范围如下:

‘a’ to ‘z’ (lowercase ascii letter)

‘A’ to ‘Z’ (uppercase ascii letter)

‘\u00C0’ to ‘\u00D6’

‘\u00D8’ to ‘\u00F6’

‘\u00F8’ to ‘\u00FF’

‘\u0100’ to ‘\uFFFE’

如下为有效的标识符:

def name
def item3
def with_underscore
def $dollarStart


如下的标识符就是非法的:

def 3tier
def a+b
def a#b


所有的关键字如果跟在一个dot后面也都是合法的标识符:

foo.as
foo.assert
foo.break
foo.case
foo.catch


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/$


有一种特殊的Groovy GStrings,也叫做插值字符串,如下所示:

def firstname = "Homer"
map."Simpson-${firstname}" = "Homer Simpson" //被插值为Simpson-Homer
assert map.'Simpson-Homer' == "Homer Simpson"


4. 字符串

Groovy支持两种字符串,一种是java原生的java.lang.String,一种是groovy.lang.GString,叫做插值字符串。

4.1 单引号字符串

单引号字符串就是java.lang.String,不支持插值,如下所示:

'a single quoted string'


4.2 字符串连接

所有的Groovy字符串均支持+操作,如下所示:

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


4.3 三单引号字符串

三单引号字符串如下所示:

'''a triple single quoted string'''


三单引号支持多行,也是java.lang.String类型,不支持插值,如下所示:

def aMultilineString = '''line one
line two
line three'''

def startingAndEndingWithANewline = '''
line one
line two
line three
'''

def strippedFirstNewline = '''\
line one
line two
line three
'''

assert !strippedFirstNewline.startsWith('\n')


4.3.1 转义特殊字符

可以使用反斜杠字符转义单引号字符,这样就可以避免字符串的终止:

'an escaped single quote: \' needs a backslash'


可以使用双重反斜杠转义反斜杠,如下所示:

'an escaped escape character: \\ needs a double backslash'


如下所示为转义字符对照表:



4.3.2 Unicode转义序列

对于键盘上没有出现的字符,可以使用一个反斜杠+’u’+四个十六进制数字表示。例如欧元符号可以使用一下方式表示:

'The Euro currency symbol: \u20AC'


4.4 双引用字符串

双引用字符串如下所示:

"a double quoted string"


对于双引用字符串来说,如果其中没有插值表达式那就是java.lang.String类型,否则就是groovy.lang.GString类型。

4.4.1 字符串插值

在Groovy所有的字符串字面量表示中,除了单引用和三引用字符串,其他的均支持插值。所谓字符串插值:就是将占位表达式的值替换到字符串中相应的位置当中,如下所示:

def name = 'Guillaume' // a plain string
def greeting = "Hello ${name}" //把name插入到greeting当中

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'


在${}当中还支持表达式,如下所示:

"The sum of 1 and 2 is equal to ${def a = 1; def b = 2; a + b}"


还支持$占位符,当使用点号表达式时:

def person = [name: 'Guillaume', age: 36]
assert "$person.name is $person.age years old" == 'Guillaume is 36 years old'


如下是非法的,会抛出groovy.lang.MissingPropertyException异常,因为系统会认为你在获取一个number的toString属性,从而报错。

def number = 3.14
shouldFail(MissingPropertyException) {
println "$number.toString()"
}


如果你想去掉GString中的插值,只需要一个反斜杠即可:

assert '${name}' == "\${name}" //"\${name}"就和普通的'${name}'相等了,因为去掉了插值


4.4.2 插值闭包表达式

插值占位符还支持闭包表达式,如下所示:

def sParameterLessClosure = "1 + 2 == ${-> 3}" //这个闭包表达式没有参数
assert sParameterLessClosure == '1 + 2 == 3'

def sOneParamClosure = "1 + 2 == ${ w -> w << 3}" //这个闭包表达式有一个java.io.StringWriter类型的参数
assert sOneParamClosure == '1 + 2 == 3'


闭包的一个最大的好处是惰性求值lazy evaluation,如下所示:

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

assert eagerGString == "value == 1"
assert lazyGString ==  "value == 1"

number = 2
assert eagerGString == "value == 1" //eagerGString的值已经被固定了
assert lazyGString ==  "value == 2" //lazyGString的值被重新计算


4.4.3 和java进行交互

当一个方法需要java.lang.String参数,传入的却是一个GString类型的参数,这个参数的toString()方法就会被自动调用,看起来像我们可以直接将一个GString赋值给一个String变量一样:

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'


4.4.4 GString和String的hashCode

GString和String的hashCode是不一样的,即便他们的最终结果是一样:

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


因此在Map当中不能不能使用GString作为Key值,如下所示:

defkey= "a"
def m = ["${key}": "letter ${key}"]    // key类型是一个GString

assert m["a"] == null                // 用一个普通String类型的key去取值,会找不到这个key,因此就会取不到值


4.5 三双引号字符串

三双引号字符串类似于双引号字符串,但是是多行的,因此又类似于三引号字符串:

def name = 'Groovy'
def template = """
Dear Mr ${name},

You're the winner of the lottery!

Yours sincerly,

Dave
"""

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


4.6 斜线字符串

除了使用引号来括住字符串,还可以使用/,斜线字符串一般用来定义正则表达式:

def fooPattern = /.*foo.*/
assert fooPattern == '.*foo.*'


只有正斜线需要用反斜线转义:

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


斜线字符串是多行的:

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


斜线字符串也可以被插值:

defcolor= 'blue'
def interpolatedSlashy = /a ${color} car/

assert interpolatedSlashy == 'a blue car'


注意:一个空的斜线字符串不能使用两个正斜线表示,因为Groovy会把其理解为注释。因此,下面的断言不会被编译,因为这个是一个非终止的语句:

assert '' == //


4.7 美元斜线字符串

这种字符串使用$/开始,使用/$结束,其中的转义字符为$:

def name = "Guillaume"
def date = "April, 1st"

def dollarSlashy = $/
Hello $name,
today we're ${date}.

$ dollar sign
$$ escaped dollar sign
\ backslash
/ forward slash
$/ escaped forward slash
$$$/ escaped opening dollar slashy
$/$$ escaped closing dollar slashy
/$

assert [
'Guillaume',
'April, 1st',
'$ dollar sign',
'$ escaped dollar sign',
'\\ backslash',
'/ forward slash',
'/ escaped forward slash',
'$/ escaped opening dollar slashy',
'/$ escaped closing dollar slashy'
].every { dollarSlashy.contains(it) }


4.8 字符串总结



4.9 字符

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


5 数字

Groovy支持不同类型的整型字面量和小数字面量。

5.1 整型字面量

支持的整型字面量和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


当使用def指明整数字面量时,变量的类型会根据数字的大小自动调整:

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


5.1.1 数字的非十进制表示

数字可以用二进制、八进制、16进制以及小数表示。

数字二进制表示如下,以ob开头:

int xInt = 0b10101111
assert xInt == 175

short xShort = 0b11001001
assert xShort == 201 as short

byte xByte = 0b11
assert xByte == 3 as byte

long xLong = 0b101101101101
assert xLong == 2925l

BigInteger xBigInteger = 0b111100100001
assert xBigInteger == 3873g

int xNegativeInt = -0b10101111
assert xNegativeInt == -175


数字的八进制表示如下,以0开头:

int xInt = 077
assert xInt == 63

short xShort = 011
assert xShort == 9 as short

byte xByte = 032
assert xByte == 26 as byte

long xLong = 0246
assert xLong == 166l

BigInteger xBigInteger = 01111
assert xBigInteger == 585g

int xNegativeInt = -077
assert xNegativeInt == -63


数字的16进制表示如下,以0x开头:

int xInt = 0x77
assert xInt == 119

short xShort = 0xaa
assert xShort == 170 as short

byte xByte = 0x3a
assert xByte == 58 as byte

long xLong = 0xffff
assert xLong == 65535l

BigInteger xBigInteger = 0xaaaa
assert xBigInteger == 43690g

Double xDouble = new Double('0x1.0p0')
assert xDouble == 1.0d

int xNegativeInt = -0x77
assert xNegativeInt == -119


5.2 小数字面量

小数字面量也跟java是一样的:

float

double

java.lang.BigDemical

如下所示:

// primitive types
float  f = 1.234
double d = 2.345

// infinite precision
BigDecimal bd =  3.456


小数还支持科学计数法:

assert 1e3  ==  1_000.0
assert 2E4  == 20_000.0
assert 3e+1 ==     30.0
assert 4E-2 ==      0.04
assert 5e-1 ==      0.5


为了精确的计算小数,groovy选择java.lang.BigDecimal作为其小数类型。此外,float和double也是支持的小数类型,但是这俩类型需要一个显式类型声明、强制类型转换或后缀声明。

def decimal = 123.456
println decimal.getClass() // class java.lang.BigDecimal


5.3 字面中的下划线

long creditCardNumber = 1234_5678_9012_3456L
long socialSecurityNumbers = 999_99_9999L
double monetaryAmount = 12_345_132.12
long hexBytes = 0xFF_EC_DE_5E
long hexWords = 0xFFEC_DE5E
long maxLong = 0x7fff_ffff_ffff_ffffL
long alsoMaxLong = 9_223_372_036_854_775_807L
long bytes = 0b11010010_01101001_10010100_10010010


5.4 数字类型后缀

可以给一个数字加入后缀把其转换为指定类型,如下所示:

TypeSuffix
BigIntegerG or g
LongL or l
IntegerI or i
BigDecimalG or g
DoubleD or d
FloatF or f
如下所示:

assert 42I == new Integer('42')
assert 42i == new Integer('42') // lowercase i more readable
assert 123L == new Long("123") // uppercase L more readable
assert 2147483648 == new Long('2147483648') // Long type used, value too large for an Integer
assert 456G == new BigInteger('456')
assert 456g == new BigInteger('456')
assert 123.45 == new BigDecimal('123.45') // default BigDecimal type used
assert 1.200065D == new Double('1.200065')
assert 1.234F == new Float('1.234')
assert 1.23E23D == new Double('1.23E23')
assert 0b1111L.class == Long // binary
assert 0xFFi.class == Integer // hexadecimal
assert 034G.class == BigInteger // octal


5.5 数学运算

以下是数学运算表(除法运算和指数运算例外):



5.5.1 除法运算

如果两个数中其中有一个是float或double类型,那么除法运算/或者/=得到的结果就是double类型,否则就是BigDemical类型。

5.5.2 指数运算

运算表如下所示:

// base and exponent are ints and the result can be represented by an Integer
assert    2    **   3    instanceof Integer    //  8
assert   10    **   9    instanceof Integer    //  1_000_000_000

// the base is a long, so fit the result in a Long
// (although it could have fit in an Integer)
assert    5L   **   2    instanceof Long       //  25

// the result can't be represented as an Integer or Long, so return a BigInteger
assert  100    **  10    instanceof BigInteger //  10e20
assert 1234    ** 123    instanceof BigInteger //  170515806212727042875...

// the base is a BigDecimal and the exponent a negative int
// but the result can be represented as an Integer
assert    0.5  **  -2    instanceof Integer    //  4

// the base is an int, and the exponent a negative float
// but again, the result can be represented as an Integer
assert    1    **  -0.3f instanceof Integer    //  1

// the base is an int, and the exponent a negative int
// but the result will be calculated as a Double
// (both base and exponent are actually converted to doubles)
assert   10    **  -1    instanceof Double     //  0.1

// the base is a BigDecimal, and the exponent is an int, so return a BigDecimal
assert    1.2  **  10    instanceof BigDecimal //  6.1917364224

// the base is a float or double, and the exponent is an int
// but the result can only be represented as a Double value
assert    3.4f **   5    instanceof Double     //  454.35430372146965
assert    5.6d **   2    instanceof Double     //  31.359999999999996

// the exponent is a decimal value
// and the result can only be represented as a Double value
assert    7.8  **   1.9  instanceof Double     //  49.542708423868476
assert    2    **   0.1f instanceof Double     //  1.0717734636432956


6 布尔型

如下所示:

def myBooleanVariable = true
boolean untypedBooleanVar = false
boolean Field = true


true和false只是两个基础的布尔值,关于更复杂的boolean操作,参考:

logical operators.

special rules

7 列表List

Groovy列表就是java.util.List,默认的子类就是java.util.ArrayList,如下所示:

def numbers = [1, 2, 3]

assert numbers instanceof List
assert numbers.size() == 3


列表中可以支持各种类型:

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


还可以定义各种类型的List,默认是ArrayList:

def arrayList = [1, 2, 3]
assert arrayList instanceof java.util.ArrayList

def linkedList = [2, 3, 4] as LinkedList
assert linkedList instanceof java.util.LinkedList

LinkedList otherLinked = [3, 4, 5]
assert otherLinked instanceof java.util.LinkedList


可以通过[]运算来获取列表的元素以及设置列表元素的值,下标可以是正数、负数、范围,还可以使用<<运算符来给list追加元素,如下所示:

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

assert letters[0] == 'a'
assert letters[1] == 'b'

assert letters[-1] == 'd'   //获取最后一个元素,-1是从数组末尾开始的第一个元素
assert letters[-2] == 'c'

letters[2] = 'C'        //赋值
assert letters[2] == 'C'

letters << 'e'        //在末尾追加一个元素
assert letters[ 4] == 'e'
assert letters[-1] == 'e'

assert letters[1, 3] == ['b', 'd']   // 一次性获取两个元素,返回一个新的List
assert letters[2..4] == ['C', 'd', 'e']    //使用一个范围获取范围内的元素,返回一个新的List


还可以组成多维List:

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


8 数组

数组需要显式定义数组的类型:

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() == 3


可以定义多维数组:

def matrix3 = new Integer[3][3]
assert matrix3.size() == 3

Integer[][] matrix2
matrix2 = [[1, 2], [3, 4]]
assert matrix2 instanceof Integer[][]


获取数组元素的方式跟List一样:

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

names[2] = 'Blackdrag'
assert names[2] == 'Blackdrag'


9 映射表Maps

如下所示:

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 //默认是LinkedHashMap类型


当获取一个map中不存在的key,会返回null:

assert colors.unknown == null


除了使用string类型的key,还可以使用其他类型的key:

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

assert numbers[1] == 'one'


如果key是一个变量,如下所示:

def key = 'name'
def person = [key: 'Guillaume']  //'Guilaume'对应的key为"key",而不是变量key所关联的值

assert !person.containsKey('name')   //不包含'name'这个key
assert person.containsKey('key')     //包含'key'这个key


要想解决上述问题,可以如下所示:

def key = 'name'
person = [(key): 'Guillaume']  //此时'Guilaume'对应的key就是变量key所对应的值

assert person.containsKey('name')
assert !person.containsKey('key')


以上就是Groovy的基本语法,关于Groovy的语法特性,还包含一下几个方面,直接看官方文档即可,有兴趣的可以了解下。

运算符 Operators

程序结构 Program structure

Groovy 面向对象语法 Object orientation

闭包 Closures

Groovy 语义 Semantics
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Groovy语法 Gradle