groovy快速上手第2篇:数据类型篇

了解一门语言,那么了解她的语法特性必不可少,groovy针对java语言的书写要求做了很多简化。下面直接开始总结groovy的语法特点

注释

groovy的注释与java保持一致

  1. 单行注释
//这是groovy的单行注释
println 'hello world'
  1. 多行注释
/*多行注释1
多行注释2 */
println 1+2
  1. doc注释,groovy3+后支持运行时保存doc内容
/**
 * 本方法实现两个数相加并返回结果
 * @param a 两个数中的一个
 * @param b 两个数中的一个
 * @return 求加结果
 */
def add(a,b){
    a+b
}
assert add(1,2) == 3
  1. shebang line
    unix下可以在文件的首航增加一个shebang line注释来表明使用什么命令来执行当前脚本
#! /user/bin/env groovy
println 'hello world'

关键字

groovy的关键字包含了java的关键字,此外还有一些groovy的特有关键字,这里不在列举每一个关键字的作用,和其他语言一样,groovy关键字不能作为变量、方法名、字段名,但可以使用取巧的方式使用关键字来定义方法名(主要应用在DSL中)。

def if = 100//编译报错
def 'abstract'() {println 'function abstract()' }
this.abstract()

标识符

使用标识符来定义变量名、方法名、字段名等信息,groovy的标识符满足以下条件

  1. 使用0-9数字,26个大小写字母,$符号,拉丁字母(话说没人用吧)
  2. 不能以数字开头

使用"."操作符时,“.”后面的属性也是有效的标识符,带点的操作符后面可接字符串格式的属性,后面接着讲字符串的相关语法,这里可以先了解下

def map = [:]//定义一个map对象
//像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中的值
map.'single quote'
map."double quote"
map.'''triple single quote'''
map."""triple double quote"""
map./slashy string/
map.$/dollar slashy string/$

//使用GString设置值
def firstname = "Homer"
map."Simpson-${firstname}" = "Homer Simpson"

assert map.'Simpson-Homer' == "Homer Simpson"

字符串

groovy有普通字符串和GString字符串(存在占位符的字符串),并允许你实例化它们

单引号字符串

单引号字符串表示普通字符串,不支持占位符的GString定义

'a single-quote string'
字符串的连接

groovy使用“+”连接字符串,和java保持一致

assert 'ab' == 'a'+'b'
三单引号字符串

支持跨行,不支持GString,并且按照编辑格式保存字符串格式,包括换行和缩进,如果你不想要自动保存其中的换行符,可以使用\去掉

String str = '''
第一行
第二行
第三行\
'''
assert str == '\n第一行\n第二行\n第三行'
转义字符

转义字符为反斜杠“\",转义的内容与大多编程语言保持一致,对于键盘上不存在unicode字符,可以使用\uxxxx(后四位16进制数)来表示

双引号字符

双引号字符如果不存在占位符的情况下是普通字符,存在占位符的情况下是GString字符串

assert "test".getClass() == String
assert "test${i1}".getClass() in GString//注意使用in关键字判断
占位符字符串GString

占位字符串GString表示一个字符串中的某一部分由其它变量组成,占位符的格式为${···},花括号内可以是引用变量,简单表达式。对于表达清晰的点式表达式可以省略花括号只使用$xx.xx表示,如果引用变量是一个对象,则将隐式的调用对象的totring()方法,

def str1 = "test"
def str2 = "this is a ${str1}"
assert str2 == 'this is a test'
assert "this is a $str1" == 'this is a test'
assert "1 + 2 = ${1+2}" == '1 + 2 = 3'
assert "1+2=${println 'hello';def a = 1,b=2,c=a+b}" == '1+2=3'//这里输出hello
def m = [a:1,b:2]
assert "$m.a" == '1' && "$m.b" == '2'
class Person{
    String name
    int age
}
def p = new Person(name:'张三',age:18)
assert "姓名:$p.name,年龄:$p.age" == "姓名:张三,年龄:18"
assert "计算1+2=${clo1(1,2)}"
assert "计算1+2=${->3}" == "计算1+2=3"//占位符内为一个闭包

注意使用简化的占位符是不允许调用方法或闭包,当使用闭包占位时将会出现有趣的情况,惰性加载,即对应的GString会在运行时才会确定最终值,参考如下示例

def num = 1
def eagerGString = "value=$num"
def lazyGString = "value=${->num}"
assert eagerGString == 'value=1'
assert lazyGString == 'value=1'
num = 2
assert eagerGString == 'value=1'
assert lazyGString == 'value=2'//当num的值变化后再获取GString时闭包的GString会更新值,普通占位符GString不会
与java的互操性

无论变量是String还是GString,当使用它作为参数调用java或者groovy的方法时,会自动调用变量的toString()方法进行自动转换

def show(String info){
    assert info.getClass() == String
    return info;
}
def p2 = new Person(name: "李四",age: 25)
def info = "姓名:$p2.name,年龄:${->p2.age}"
assert show(info) == "姓名:李四,年龄:25"
GString与String的不同处

而这属于不同的类,因此即便表示的是同一个字符串,它们的hashCode也不相同,并且GString还有惰性加载,他的hash值可能发生变化,因此不建议使用GString作为Map的key

num=2
assert "value=2".hashCode() != "value=$num".hashCode()
def gStr1 = "value=$num"
def map = ["value=$num":100]
assert map."value=2" == null
三双引号字符串

和三单引号字符串相似,但支持占位符GString

斜线字符串

groovy支持以斜线开头斜线结尾的字符串,并且斜线字符串还支持多行格式和GString,如果一个字符串既包含单引号又包含双引号,使用斜线字符串定义不用使用转义字符。当然斜线字符本身需要转义,转义字符串本身不需要转义,其次不能以转义字符结尾。斜线字符串的作用是定义尽量不使用转义字符的字符串

//str3并不是以制表符\t结尾,而是以一个反斜杠和字符t结尾,这意味着非打印字符只能使用unicode形式
def str3 = /this is a 'text' "string"\t/
assert str3 == "this is a 'text' \"string\"\\t"

因为斜杠字符串如果要包含斜杠的话需要使用转义字符,因此如果要以转义字符结尾的话将会导致终止斜线字符被转义,这里可以使用一个小技巧来实现以反义字符结尾

//def str4 = /text end with \/ //编译错误
def str5 = /text ends with ${'\\'}/使用占位符GString实现反斜线结尾
str5 == 'text ends with \\'
美元斜线字符串

美元斜线字符串显然是为了客服斜线字符串的问题,当字符串里面包括正斜线反斜线等内容时,使用美元斜线字符串似乎是个不错的选择,它支持多行字符串和GString,发现一个bug是不能再美元斜线字符串中定义/$后面紧接非空字符的字符串(类似/$abc这样的字符串),会报No such propety错误

def name = 'Guillaume'
def date = 'April,1st'
def dollarSlash = $/
    hello $name,
    today we're ${date}.
    $ dollar sign
    $$ escape dollar sign
    \ backslashy
    / forward slash
    $/ escape forward slash
    $$$/ escape opening dollar slash
    $/$$ escape close dollar slash
/$

字符

groovy中没有明确的字符文字,但你可以通过强制转换为字符,有三种转换方式

char char1 = 'A'
def char2 = 'A' as char
def char3 = (char) 'A'

数值

整型数值

与java相同,byte、short、int、long分别从一个字节倍增到8个字节,在使用上比java更加方便,同时当出现像下强转(大数转为小数)时通过截取地位字节实现,自动转换无需显示强转

byte b = 1 //无需java那样需要显式强转,如果超出长度自动截取低位值
short s = 1
int i10 = 1
long l = 1
BigInteger bi = 10

当使用def定义变量式,将自动根据赋值的数值大小确定变量的具体类型

def d1 = 1
assert d1 instanceof Integer
def d2 = 2147483648 + 1//2147483648 = Integer.MAX_VALUE+1,不能使用这个表达式赋值,因为默认两个Integer相加还是Integer类型
assert d2 instanceof Long
def d3 = 9223372036854775808 + 1
assert d3 instanceof BigInteger
数字的其他格式

和java一样,数字也可以使用二进制、八进制、十六进制表示,二进制以ob开头,8进制以0开头,16进制以0x开头,此外对于较长的数字可以使用下划线分隔以便更好的目视。

def bint = 0b1001
def oint = 017
def xint = 0xabc
def i11 = 123_343_123
浮点类型数值

浮点类型包括float和double,分别占长度4字节到8字节,大浮点数字可以使用BigDecimal表示,同时可以使用指数形式表示浮点数值

float f5 = 1.1
double d4 = 1.4
BigDecimal bi2 = 2.1
assert 1e4 == 10000.0
assert 1e4 == 10000
assert 3e-1 == 0.3
assert 5E-2 == 0.05

可以通过数字后缀特定字符来强转数值为指定类型的数字

assert 100i instanceof Integer//100默认值为Integer,可以后缀i强转
assert 100f instanceof Float//后缀f强转float
assert 100D instanceof Double//后缀D或d强转double
assert 100g instanceof BigInteger//后缀g
assert 100.0 instanceof BigDecimal//默认
assert 010g instanceof BigInteger//八进制后缀g
assert 0b1001l instanceof Long//二进制后缀l
assert 0xabcg instanceof BigInteger//16进制后缀g
数值的数学计算结果

参见下图,可以很清晰的看到两个数值的计算结果只会导致结果像更大类型的值拓展,并且自int类型起步,超过int类型类型以最大的那个数值的类型为准,即便发生溢出也不会再向上扩大了(即两个int计算结果一定为int,int与long计算结果为long)
在这里插入图片描述
对于除法由特殊规定,当被除数和除数有一个为float或double时,则结果为Double,否则结果为BigDecimal,对于除法产生的精度问题,当能够除尽时将会保留全部精度,不能除尽时将保留10位有效数字(浮点型数值的二进制表示方法)

assert 1234567891f / 1e10 != 0.1234567891
assert 1234567891 / 1e10 == 0.1234567891
幂运算值

幂运算使用 ** 运算符,其结果取决于两个操作数和结果,文档复杂待定

布尔值

布尔值使用特殊的数据类型表示true和false,占用1字节,与java不同的是groovy有特殊的规则来判断一个非布尔值的真假,groovy的规则是判断目标有东西而"非空"则为true,否则为false。这里的非空对于普通对象来说非null,对于集合来说非空集合,对于枚举来说有元素,对于字符串来说非空串,对于数值来说非0.最后一点对于普通类对象来说,可以通过覆写asBoolean方法来自定义它实例的布尔判断

//布尔值直接判断
assert true
assert !false
//非空集合为ture,空集合为false
assert [1,2,3]
assert ![]
assert ('a' =~ /a/)
assert !('a' =~ /b/)
assert [a:1]
assert ![:]
//非空迭代器为true,空迭代器为false
assert [0].iterator()
assert ![].iterator()
def v = [0] as Vector;
//非空列举为true,空列举为false
Enumeration enumeration  = v.elements();
assert enumeration
enumeration.nextElement()
assert !enumeration
//非空字符为true,否则为false
assert 'a'
assert !''
//非0值为true,0值为false
assert 1
assert !0
//普通对象为true,null值为false
assert new Object()
assert !null
//自定义类的布尔输出结果
class MyObj{
    boolean asBoolean(){
        false
    }
}
assert !new MyObj()

List

groovy使用一个方括号括起来多个值之间通过逗号分隔的结构来定义List,具体结构使用java的List(默认实现为ArrayList),如果需要其他结构的List,可以通过as关键字另行制定。

  • 访问List元素通过list[元素索引位置]来访问,正索引表示从前到后,负索引表示从后到前
  • 可以通过逗号分割的多个索引位置来获取一个子List
  • 可以通过“…”来获取一个连续范围内的子List
  • 可以通过<< 运算符来讲元素添加到List中
def list1 = [1,2,'a',"string info"]
def list2 = [3,4,6] as LinkedList
assert list2 instanceof LinkedList
assert list1[0] == 1
assert list1[-1] == 'string info'
assert list1[1,3] == [2,'string info']
assert list1[0..2] == [1,2,'a']
list1 << 'b'
assert list1[-1] == 'b'
list1[0] = '10'
assert list1[0] == '10'

数组

groovy对数组的语法重用了List,其对元素的访问也和List一样,但数组不支持 << 操作符,此外groovy支持java风格的语法

assert new int[]{1,2,3} instanceof int[]//java风格
assert (int[])[1,2,3] instanceof int[]//强转
int[] arr1 = [4,5,6]//显示类型定义
assert arr1 instanceof int[]
def arr2 = [7,8,9] as int[]//as关键字
assert arr2 instanceof int[]
assert arr1[1] == 5
arr1[1] = 15
assert arr1[1] == 15
assert arr1[-1] == 6
assert arr1[0,1] == (int[])[4,15]
assert arr1[0..2] == (int[])[4,15,6]

Map

groovy使用一个中括号括起来、冒号分隔键值对,多个键值对之家通过逗号分隔的方式定义map,map的key为标准的标识符字符串时可以省略双引号(访问或者赋值均可省略)。

  • map的key建议使用字符串、数值等hashcode不会变化的类型值,不建议使用闭包的GString等
  • 访问map时key是变量时可以通过GString方式或者讲变量用小括号括起来的方式,当然也可以是用get方法,当使用括号时是告诉解释器传递的是变量而非字符串常量
def color = [blue:'#0000FF',red:'#FF0000',green:'00FF00']
assert color.blue == '#0000FF'
assert color['red'] == '#FF0000'
color.pink = '#FF00FF'
color['yellow'] = '#FFFF00'
assert color['pink'] == '#FF00FF'
assert color instanceof LinkedHashMap
assert color.unknown == null
color.'my favor color' = '#0F0F0F'
assert color.'my favor color' == '#0F0F0F'
def str6 = 'pop color'
color."$str6" = '#FFFFFF'
assert color["$str6"] == '#FFFFFF'
def str7 = 'bad color'
color[(str7)] = '#000000'
assert color.(str7) == '#000000'
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值