在写单元测试的时候, 我这里推荐使用spock framework, 但是spock支持使用groovy的语言, 今天我们先来简单学习groovy的基本语法
官网学习链接地址: http://groovy-lang.org/syntax.html

groovy的语法和python有点相似

1. 注释


1.1 单行注释


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

1.2 多行注释


/* 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 Groovy文档注释


/**
* 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}"
  }
}

2. 关键字


  • 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

3. 标识符


3.1 普通标识符


  • 标识符以字母,美元或下划线开头,不能以数字开头,接下来的字符可以包含字母和数字。
  • 所有关键字在跟随 . 也是有效的标识符。
// 正确
def name            
def item3
def with_underscore
def $dollarStart

// 错误
def 3tier
def a+b
def a#b

// 正确
foo.as
foo.assert
foo.break
foo.case
foo.catch

3.2 引号标识符

引号标识符出现在表达式 . 后面。例如,person.name 表达式的名称部分可用引号引起。例如 person.“name” 或 person.'name'。 当某些标识符包含被 Java 语言规范禁止的非法字符,但使用引号引起时在 Groovy 中是允许的。例如,像破折号,空格,感叹号等字符。

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"

map.'single quote'
map."double quote"
map.'''triple single quote'''
map."""triple double quote"""
map./slashy string/
map.$/dollar slashy string/$

def firstname = "Homer"
map."Simpson-${firstname}" = "Homer Simpson"
assert map.'Simpson-Homer' == "Homer Simpson"

4. 字符串


  • java.lang.String // 不支持插值
  • GStrings (groovy.lang.GString) // 支持插值

4.1 单引号字符串


单引号字符串为 java.lang.String,不支持插值。

'ab' == 'a' + 'b' // 字符串拼接

4.2 三重单引号字符串


三重单引号字符串为 java.lang.String,不支持插值,三重单引号字符串是多行的,不要用换行符来换行。

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

def strippedFirstNewline = '''\   // 字符串包含换行符作为第一个字符,可以通过用反斜杠转义换行来剥离该字符?
line one
line two
line three
'''
assert !strippedFirstNewline.startsWith('\n')

4.3 特殊转换符


Escape  sequence Character
'\t'    tabulation
'\b'    backspace
'\n'    newline
'\r'    carriage return
'\f'    formfeed
'\' backslash
''' single quote (for single quoted and triple single quoted strings)
'"' double quote (for double quoted and triple double quoted strings)

4.4 双引号字符串


  • 若没有插值表达式(interpolated expression),则双引号字符串为 java.lang.String,但若存在插值表达式,则为 groovy.lang.GString。
  • 除了单引号和三引号字符串外,任何字符串支持插值。
  • 插值是在对字符串进行评估时用其值替换字符串中的占位符的行为,占位符表达式由 ${}。
  • ${} 占位符之间不仅允许表达式,语句也被允许。但语句的值只是 null,因此如果在该占位符中插入了几个语句,最后一个应该以某种方式返回一个有意义的值(不推荐插入语句)。
  • 在 . 表达式使用 $ 占位符,但表达式中若有方法调用,闭包的花括号或算术运算符将无效。
  • 若在 $ 使用转义符号 \,则不有会插值效果。
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 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'

def number = 3.14
shouldFail(MissingPropertyException) {
   println "$number.toString()" // 语句将抛出一个 groovy.lang.MissingPropertyException,因为 Groovy 认为您正在尝试访问该数字的 toString 属性,该属性不存在,可以理解 Groovy 解析成 "${number.toString}()"。
}

4.5 反斜杠字符串


使用 / 作为分隔符的斜线字符串。Slashy 字符串对于定义 正则表达式 特别有用,因为不需要转义反斜杠。

也是多行也能被插值。

一个空的斜线字符串不能用双正斜杠表示,因为 Groovy 解析器被理解为单行注释。

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'

4.6 美元转义符


  • Dollar slashy string 是多行 GStrings,分隔以 $/ 开头和以 /$ 结尾。
  • 使用转义符 $ 可以转义 $ 和正斜线 /。
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 dollar slashy string delimiter
/$
assert [
   'Guillaume',
   'April, 1st',
   '$ dollar sign',
   '$ escaped dollar sign',
   '\\ backslash',
   '/ forward slash',
       '$/ escaped forward slash',
       '/$ escaped dollar slashy string delimiter'

      ].each { dollarSlashy.contains(it) }

4.7 字符


与 Java 不同,Groovy 没有明确的字符字面量。但可以通过三种不同的方式明确地将 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
// 当字符被保存在一个变量中时,使用第一种方式好,而当一个 char 值必须作为方法调用的参数传递时使用另外两种方式好。

5. 数字常量


5.1 常量类型


  • 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.2 小数


类型:

  • float
  • double
  • java.lang.BigDecimal
  • Groovy 使用 BigDecimal 是小数的默认值。另外,float 和 double 都支持,但需要一个明确的类型声明、类型强制或后缀。
  • 在方法或闭包中接受一个类型 BigDecimal 类型的值,即使方法参数类型是 float 和 double。
  • 不能使用二进制,八进制或十六进制表示来表示小数。

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

6. 布尔


  • true 和 false 是唯一的两个原始布尔值。
  • Groovy 有一个特殊的规则(通常称为Groovy Truth),用于将非布尔对象强制为一个布尔值。
    def myBooleanVariable = true
    boolean untypedBooleanVar = false
    booleanField = true

7. 列表


  • Groovy 使用 , 分隔的值,用 [] 括起来表示 lists。
  • 因为 Groovy 没有定义自己的集合类,Groovy lists 是 JDK java.util.List,默认使用的实现类是 java.util.ArrayList,除非手动通过操作符 as 和声明类型指定。
  • lists 可以存放多种类型元素。
def numbers = [1, 2, 3]
assert numbers instanceof List  
assert numbers.size() == 3  

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

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 中的元素,可用 << leftShift 运算符将元素附加到 list 中。
  • 索引范围的值:[-list.size(), list.size() - 1],小于最小索引获取元素报索引越界,大于最大索引获取元素是 null(这点不同 Java)。
  • list 元素可以是另一个 list。
def letters = ['a', 'b', 'c', 'd']

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

assert letters[-1] == 'd'    
assert letters[-2] == 'c'

letters[2] = 'C'            
assert letters[2] == 'C'

letters << 'e'                          // 添加元素到 list 尾部。             
assert letters[4] == 'e'
assert letters[-1] == 'e'               // 注意这个 索引 -1 上的值是最后一个元素

assert letters[1, 3] == ['b', 'd']      // 注意这个返回一个新的 list  
assert letters[2..4] == ['C', 'd', 'e'] // 注意这个返回一个新的 list

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

8. 数组


  • 定义数组 Groovy 重用 list 定义方式,若要明确数组类型可通过 as 强制或类型声明。
    
    String[] arrStr = ['Ananas', 'Banana', 'Kiwi']  // 类型声明

assert arrStr instanceof String[]
assert !(arrStr instanceof List)

def numArr = [1, 2, 3] as int[] // as 强制

assert numArr instanceof int[]
assert numArr.size() == 3


* 支持定义多维数组。
* Groovy 不支持 Java 数组初始化符号 {},因为 {} 可能会被曲解成 Groovy 闭包的符号。

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'


# 8. Maps

-----

* Groovy 具有 maps 关联键映射到值,使用冒号分隔键和值,并使用逗号分隔每个键/值对,以及由方括号包围的整个键和值。
* Groovy 创建的 map 使用的是 java.util.LinkedHashMap 的实例。

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

assert colors.unknown == null // 不存在 key 返回 null


可以使用其他类型值作为键。

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

def key = 'name'
def persons = [key: 'Guillaume']

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

person = [(key): 'Guillaume']

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


若变量或表达式作为 map 中的键使用,必须用括号括住变量或表达式

def key = 'name'
def persons = [(key): 'Guillaume']

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