美文网首页Groovy专题
Groovy基础语法 - 标识符&字符串

Groovy基础语法 - 标识符&字符串

作者: CXY_XZL | 来源:发表于2022-08-24 17:04 被阅读0次

1.标识符

1.1普通标识符

标识符以字母、美元或下划线开头。它们不能以数字开头。
字母可以介于以下范围内:

  • “a” 到 “z”(小写 ascii 字母)
  • “A”到“Z”(大写的 ascii 字母)
  • “\u00C0”到“\u00D6”
  • “\u00D8”到“\u00F6”
  • “\u00F8”到“\u00FF”
  • “\u0100”到“\uFFFE”

然后,以下字符可以包含字母和数字。
以下是有效标识符的几个示例(此处为变量名称):

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

1.2带引号的标识符

带引号的标识符显示在虚线表达式的点之后。例如,person.name表达式的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"  //true
assert map.'with-dash-signs-and-single-quotes' == "ALLOWED"   //true

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"

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

2.字符串

文本文本以称为字符串的字符串链的形式表示。Groovy允许您实例化 java.lang.String 对象,以及GStrings(groovy.lang.GString),这在其他编程语言中也称为插值字符串。

2.1单引号字符串

单引号字符串是一系列用单引号括起来的字符:

'a single-quoted string'

单引号字符串是普通的java.lang.String,不支持插值。

2.2字符串连接

所有 Groovy 字符串都可以与运算符+连接:

assert 'ab' == 'a' + 'b'  //true

2.3三重单引号字符串

'''a triple-single-quoted string'''

三重单引号字符串是普通的java.lang.String,不支持插值。

三重单引号字符串可能跨越多行。字符串的内容可以跨越行边界,而无需将字符串拆分为多个部分,也无需串联或换行符转义字符:

def aMultilineString = '''line one
line two
line three'''

如果代码缩进(例如在类的方法正文中),则字符串将包含缩进的空格。Groovy 开发工具包包含用于使用String#stripIndent()方法去除缩进的方法,以及使用采用分隔符字符来标识要从字符串开头删除的文本的String#stripMargin()方法。

创建字符串时,如下所示:

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

会注意到,生成的字符串包含换行符作为第一个字符。可以通过用反斜杠转义换行符来剥离该字符:

def strippedFirstNewline = '''\
line one
line two
line three
'''

assert !strippedFirstNewline.startsWith('\n')  //true

2.3双引号字符串

双引号字符串是一系列用双引号括起来的字符:

"a double-quoted string"

如果没有java.lang.String内插表达式,双引号字符串是纯文本的,但如果存在groovy.lang.GString内插,则为实例。
要转义双引号,可以使用反斜杠字符:“双引号:\”。

2.3.1字符串插值

任何 Groovy 表达式都可以在所有字符串文本中进行插值,单引号和三重单引号字符串除外。插值是在计算字符串时将字符串中的占位符替换为其值的操作。占位符表达式由 ${}包围。对于明确的虚线表达式,可以省略大括号,即在这些情况下我们可以只使用$ 前缀。如果将 GString 传递给采用 String 的方法,则占位符内的表达式值将计算为其字符串表示形式(通过调用toString()该表达式),并将生成的 String 传递给该方法。
在这里,我们有一个字符串,其中包含一个引用局部变量的占位符:

def name = 'Guillaume' // a plain string
def greeting = "Hello ${name}"

assert greeting.toString() == 'Hello Guillaume'  //true

任何Groovy表达式都是有效的,正如我们在这个例子中看到的算术表达式:

def sum = "The sum of 2 and 3 equals ${2 + 3}"
assert sum.toString() == 'The sum of 2 and 3 equals 5'  //true

不仅允许在${}占位符之间使用表达式,而且语句也允许使用。但是,语句的值只是null 。因此,如果在该占位符中插入了多个语句,则最后一个语句应以某种方式返回要插入的有意义的值。例如,“1 和 2 之和等于 ${def a = 1;def b = 2;a + b}“受支持并按预期工作,但一个好的做法通常是坚持使用 GString 占位符内的简单表达式。

除了${}占位符之外,我们还可以使用一个单独的符号$作为虚线表达式的前缀:

def person = [name: 'Guillaume', age: 36]
assert "$person.name is $person.age years old" == 'Guillaume is 36 years old'  //true

但只有 a.ba.b.c等形式的虚线表达式 才有效。包含括号(如方法调用)、闭包的大括号、不属于属性表达式的点或算术运算符的表达式将无效。给定以下数字的变量定义:

def number = 3.14

以下语句将抛出一个groovy.lang.MissingPropertyException,因为Groovy认为您正在尝试访问该数字的toString属性,该属性不存在。
同样,如果表达式不明确,则需要保留大括号:

String thing = 'treasure'
assert 'The x-coordinate of the treasure is represented by treasure.x' ==
    "The x-coordinate of the $thing is represented by $thing.x"   // <= Not allowed: ambiguous!!
assert 'The x-coordinate of the treasure is represented by treasure.x' ==
        "The x-coordinate of the $thing is represented by ${thing}.x"  // <= Curly braces required

如果需要转义 GString 中的 ${}$占位符,以便它们按原样显示而不进行插值,则只需使用反斜杠字符来转义美元符号:

assert '$5' == "\$5"
assert '${name}' == "\${name}"

2.3.2插值闭包表达式的特殊情况

到目前为止,我们已经看到我们可以在${}占位符内插入任意表达式,但是闭包表达式有一个${→}表示法。当占位符包含箭头时,表达式实际上是一个闭包表达式 — 您可以将其视为前面有一个美元前缀的闭包:

def sParameterLessClosure = "1 + 2 == ${-> 3}" 
assert sParameterLessClosure == '1 + 2 == 3'  //true

def sOneParamClosure = "1 + 2 == ${ w -> w << 3}" 
assert sOneParamClosure == '1 + 2 == 3'   //true

闭包是一个无参数的闭包,它不接受参数
此处,闭包采用单个java.io.StringWriter参数,您可以使用<< leftShift 运算符向其追加内容。在任一情况下,两个占位符都是嵌入式闭包。

从外观上看,它看起来像是定义要插值的表达式的一种更冗长的方式,但与单纯表达式相比,闭包具有一个有趣的优势:惰性求值。

让我们考虑以下示例:

def number = 1 
def eagerGString = "value == ${number}"
def lazyGString = "value == ${ -> number }"

assert eagerGString == "value == 1"   //true
assert lazyGString ==  "value == 1"     //true

number = 2 
assert eagerGString == "value == 1"    //true
assert lazyGString ==  "value == 2"      //true

2.3.3与java的互操作性

当一个方法(无论是在Java还是Groovy中实现)需要一个java.lang.String,但是我们传递一个groovy.lang.GString实例时,GString的方法会自动透明地调用toString()

String takeString(String message) {         
    assert message instanceof String        
    return message
}

def message = "The message is ${'hello'}"   
assert message instanceof GString           //true

def result = takeString(message)            
assert result instanceof String                //true
assert result == 'The message is hello'    //true
  • 我们创建一个 GString 变量
  • 我们仔细检查它是否是 GString 的一个实例
  • 然后,我们将该 GString 传递给一个将 String 作为参数的方法。
  • taskString()该方法的签名明确表示其唯一参数是 String
  • 我们还验证该参数确实是字符串而不是 GString。

2.3.4GString & String hashCodes

虽然可以使用内插字符串来代替普通的Java字符串,但它们与字符串在特定方面有所不同:它们的哈希码是不同的。普通 Java 字符串是不可变的,而生成的 GString 字符串表示形式可能会有所不同,具体取决于其内插值。即使对于相同的结果字符串,GStrings 和 Strings 也不具有相同的哈希代码。

assert "one: ${1}".hashCode() != "one: 1".hashCode() //fasle

应该避免使用GString作为Map键的具有不同哈希值的GString和字符串,特别是当我们尝试检索具有字符串而不是GString的关联值时。

def key = "a"
def m = ["${key}": "letter ${key}"]     

assert m["a"] == null //true
  • 使用初始对创建映射,其键为 GString
  • 当我们尝试使用 String 键获取值时,我们将找不到它,因为 Strings 和 GString 具有不同的哈希值

2.4三重双引号字符串

三重双引号字符串的行为类似于双引号字符串,此外,它们是多行的,就像三重单引号字符串一样。

def name = 'Groovy'
def template = """
    Dear Mr ${name},

    You're the winner of the lottery!

    Yours sincerly,

    Dave
"""

assert template.toString().contains('Groovy')  //true

双引号和单引号都不需要在三重双引号字符串中转义。

2.4.1转义特殊字符

您可以使用反斜杠字符转义单引号,以避免终止字符串文本:

'an escaped single quote: \' needs a backslash'

您可以使用双反斜杠转义转义字符本身:

'an escaped escape character: \\ needs a double backslash'

一些特殊字符还使用反斜杠作为转义字符:


转义字符.png

2.4.2统一码转义序列

对于键盘上不存在的字符,可以使用 unicode 转义序列:反斜杠,后跟“u”,然后是 4 个十六进制数字。

例如,欧元货币符号可以用以下方式表示:

'The Euro currency symbol: \u20AC'

2.5斜线

除了通常的带引号的字符串之外,Groovy还提供斜杠字符串,用作开始和结束分隔符。斜杠字符串对于定义正则表达式和模式特别有用,因为不需要转义反斜杠
斜杠字符串的示例:

def fooPattern = /.*foo.*/
assert fooPattern == '.*foo.*'  //true

只有正斜杠需要用反斜杠进行转义:

def escapeSlash = /The character \/ is a forward slash/
assert escapeSlash == 'The character / is a forward slash'  //true

斜线字符串是多行的:

def multilineSlashy = /one
    two
    three/

assert multilineSlashy.contains('\n')

斜杠字符串可以被认为是定义GString的另一种方式,但具有不同的转义规则。因此,它们支持插值:

def color = 'blue'
def interpolatedSlashy = /a ${color} car/

assert interpolatedSlashy == 'a blue car'  //true

2.5.1特殊情况

空斜杠字符串不能用双正斜杠表示,因为Groovy解析器将其理解为行注释。这就是为什么下面的断言实际上不会编译,因为它看起来像一个非终止语句:

assert '' == //     //compilation error

由于斜杠字符串主要是为了让正则表达式更容易而设计的,因此GStrings中的一些错误就像$()$5将适用于斜杠字符串。
请记住,转义反斜杠不是必需的。另一种思考方式是,实际上不支持逃避。斜杠字符串/\t/将不包含制表符,而是包含后跟字符“t”的反斜杠。仅允许斜杠字符转义,即 /\/folder/将是一个包含 '/folder'的斜杠字符串。斜杠转义的结果是斜杠字符串不能以反斜杠结尾。否则,这将转义斜杠字符串终止符。您可以改用一个特殊的技巧./ends with slash ${'\'}/,但最好避免在这种情况下使用斜杠字符串。

2.6美元斜线

美元斜线字符串是多行GStrings,用$/开口和/$结束分隔。转义字符是美元符号,它可以转义另一美元或正斜杠。只有在与特殊使用发生冲突时才需要转义美元和正斜杠字符。这些字符通常表示GString占位符,因此$foo可以通过转义美元将这四个字符输入到美元斜杠字符串中,即$$foo.同样,如果您希望一个美元斜杠的收尾分隔符出现在字符串中,则需要对其进行转义。
以下是一些示例:

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) }   //all true

它的创建是为了克服斜杠字符串转义规则的一些限制。当它的转义规则适合您的字符串内容时使用它(通常,如果它有一些您不想转义的斜杠)。


2.7字符串汇总表

汇总表.png

2.8字符

与Java不同,Groovy没有明确的字符文字。但是,您可以通过三种不同的方式明确地使Groovy字符串成为实际字符:

char c1 = 'A' 
assert c1 instanceof Character  //true

def c2 = 'B' as char 
assert c2 instanceof Character   //true

def c3 = (char)'C' 
assert c3 instanceof Character   //true

相关文章

  • Groovy基础语法 - 标识符&字符串

    1.标识符 1.1普通标识符 标识符以字母、美元或下划线开头。它们不能以数字开头。字母可以介于以下范围内: “a”...

  • Groovy语法基础二

    上接 Groovy语法基础一 五、数据类型 1、字符型 Groovy 中没有单独的字符类型,可以将字符串类型“显...

  • Android之Gradle<第二篇>:Groovy基础

    下面贴出Groovy基础的已有链接: Groovy<第一篇>:Groovy 前言Groovy<第二篇>:基础语法(...

  • Groovy介绍

    参考:深入理解Android之Gradle Groovy与Java的区别Groovy语法Groovy基础——Clo...

  • Gradle 之 Android 中的应用

    在上一篇文章中 Gradle 之语言基础 Groovy 主要介绍了 Groovy 的基础语法(如果没有 Groov...

  • Groovy基础语法

    1.实现循环的方式 1.for in upto 3.times 安全导航操作符 1.null检查处理 使用?.在空...

  • python数据处理入门(1)2020-01-08

    编码工具 基础语法标识符 数据类型 字符串拼接 使用+进行拼接 字符串的格式化输出 format 第二种forma...

  • Gradle开发-Groovy字符串

    ##Groovy 字符串 前言:因为笔者本身就有 Java 基础,因此在学习 Groovy 时,主要学习 Groo...

  • python学习总结

    python基础语法总结 参考:Python基础语法总结 参考:1.Python标识符 在 Python 里,标识...

  • 一、Groovy语法(一):基础语法

    Groovy基础语法 1.Groovy中的变量 1.1、变量的类型:基本类型(java中的int,float,do...

网友评论

    本文标题:Groovy基础语法 - 标识符&字符串

    本文链接:https://www.haomeiwen.com/subject/frqogrtx.html