优秀的编程知识分享平台

网站首页 > 技术文章 正文

Groovy基础知识超详细快速入门(groovy中文教程)

nanyue 2024-08-23 18:35:22 技术文章 6 ℃

作者:杨龙,叩丁狼教育

本文参考groovy手册,对Groovy的基础语法做一个快速介绍。

注释

单行注释

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

多行注释

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

Groovy文档注释

GroovyDoc 遵循与 Java 自己的 JavaDoc 相同的约定,可以使用与 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}"
 }
}

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

标识符

普通标识符

  • 标识符以字母,美元或下划线开头,不能以数字开头,接下来的字符可以包含字母和数字。
  • 所有关键字在跟随 . 也是有效的标识符。
// 正确
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

引号标识符

引号标识符出现在表达式 . 后面。 例如,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."Simson-${firstname}" = "Homer Simson" // 支持插值
assert map.'Simson-Homer' == "Homer Simson"

字符串

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

单引号字符串

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

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

三重单引号字符串

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

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

特殊转移符

Unicode形式转义符

用于键盘上不存在的字符。

'The Euro currency symbol: \u20AC'

双引号字符串

  • 若没有插值表达式(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}()"。
}

三重双引号字符串

三重双引号字符串表现和双引号字符串一样,另外它是多行的。

def name = 'Groovy'
def template = """
 Dear Mr ${name},
 You're the winner of the lottery!
 Yours sincerly,
 Dave
"""
assert template.toString().contains('Groovy')

反斜线字符串

  • 使用 / 作为分隔符的斜线字符串。 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'

美元转义符

  • 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) }

字符串汇总

字符

与 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 值必须作为方法调用的参数传递时使用另外两种方式好。

数字常量

支持的常量类型

  • byte
  • char
  • short
  • int
  • long
  • java.lang.BigInteger
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

非十进制表示法

二进制表示

二进制数字以 0b 前缀开头:

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

十六进制表示

十六进制数字以 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

小数

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

下划线在数字常量中的使用

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

数值类型强制表示

使用后缀强制一个数值的类型:

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

计算结果类型判定

  • 运算结果类型取决于表达中类型数值范围最大的,但任何与 float 及 double 运算结果都是 double。

除法操作

  • 正数相除可以使用 / 或方法 intdiv()。
  • BigDecimal 类型相除使用方法 divide。
def a = 2.intdiv(2) // 1
def b = 2.0.divide(1.0) // 1
def c = 2.000000.divide(1.00, 1, RoundingMode.HALF_UP) // 2.0

幂运算

幂运算符由 ** 运算符表示,其中有两个参数:基数和指数。 幂运算符的结果取决于其操作数和操作结果。

  • 指数是小数
  • 若结果可以为 Integer 类型,则返回是 Integer 类型值。
  • 若结果可以为 Long 类型,则返回 Long 类型值。
  • 其它情况返回 Double 类型值。
  • 指数是正数
  • 负数
  • 若结果值适合该类型,则返回 Integer、 Long 或 Double 类型值。
  • 正数或 0
  • 若基数是 BigDecimal 类型,则返回是 BigDecimal 类型值。
  • 若基数是 BigInteger 类型,则返回是 BigInteger 类型值。
  • 若基数是 Integer 类型,且结果值适合该类型,则返回 Integer 或 BigInteger类型值。
  • 若基数是 Long 类型,且结果值适合该类型,则返回 Long 或 BigInteger 类型值。
// 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

布尔

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

列表

  • 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 

数组

  • 定义数组 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'

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')
最近发表
标签列表