概述
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语法的关键字如下所示:
as | assert | break | finally | implements | new | switch | trait |
---|---|---|---|---|---|---|---|
case | catch | class | false | import | null符号 | switch | true |
const | continue | def | for | in | package | this | try |
default | do | else | goto | instanceof | return | throw | while |
enum | enum | extends | if | interface | super | throws |
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 数字类型后缀
可以给一个数字加入后缀把其转换为指定类型,如下所示:
Type | Suffix |
---|---|
BigInteger | G or g |
Long | L or l |
Integer | I or i |
BigDecimal | G or g |
Double | D or d |
Float | F 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
最后
以上就是文艺大船为你收集整理的Gradle基础之Groovy语法的全部内容,希望文章能够帮你解决Gradle基础之Groovy语法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复