Gradle基础之Groovy语法

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是一样的:

  1. byte
  2. char
  3. short
  4. int
  5. long
  6. 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

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值