Preface:
Groovy strings come in two flavors: plain strings and GStrings. Plain strings are instances of java.lang.String , and GStrings are instances of groovy.lang.GString .GStrings allow placeholder expressions to be resolved and evaluated at runtime. Many scripting languages have a similar feature, usually called string interpolation, but it’s more primitive than the GString feature of Groovy. Let’s start by looking at each flavor of string and how they appear in code.
Varieties of string literals:
Java allows only one way of specifying string literals: placing text in quotes “like this.” If you want to embed dynamic values within the string, you have to either call a formatting method (made easier but still far from simple in Java 1.5) or concatenate each constituent part. If you specify a string with a lot of backslashes in it (such as a Windows file name or a regular expression), your code becomes hard to read, because you have to double the backslashes. If you want a lot of text spanning several lines in the source code, you have to make each line contain a complete string (or several complete strings).
Groovy recognizes that not every use of string literals is the same, so it offers a variety of options. These are summarized in table 3.5.
The aim of each form is to specify the text data you want with the minimum of fuss. Each of the forms has a single feature that distinguishes it from the others:
- The single-quoted form
- The double-quoted form
- The triple-quoted form
- The slashy form
Groovy uses a similar mechanism for specifying special characters, such as linefeeds and tabs. In addition to the Java escapes, dollar signs can be escaped in Groovy to allow them to be easily specified without the compiler treating the literal as a GString. The full set of escaped characters is specified in table 3.6.
Note that in a double-quoted string, single quotes don’t need to be escaped, and vice versa. In other words, 'I said, "Hi."' and "don't" both do what you hope they will. For the sake of consistency, both still can be escaped in each case. Likewise, dollar signs can be escaped in single-quoted strings, even though they don’t need to be. This makes it easier to switch between the forms.
Note that Java uses single quotes for character literals, but as you have seen, Groovy cannot do so because single quotes are already used to specify strings. However, you can achieve the same as in Java when providing the type explicitly:
The
java.lang.String 'x' is coerced into a java.lang.Character . If you want to coerce a string into a character at other times, you can do so in either of the following ways:
Whichever literal form is used, unless the compiler decides it is a
GString, it ends up as an instance of java.lang.String , just like Java string literals. So far, we have only teased you with allusions to what GStrings are capable of. Now it’s time to spill the beans.
Working with GStrings:
GStrings are like strings with additional capabilities. They are literally declared in double quotes. What makes a double-quoted string literal a GString is the appearance of placeholders. Placeholders may appear in a full ${expression} syntax or an abbreviated $reference syntax. See the examples in listing 3.2.
- Listing 3.2 Working with GStrings
Although
GStrings behave like java.lang.String objects for all operations that a programmer is usually concerned with, they are implemented differently to capture the fixed and the dynamic parts (the so-called values) separately. This is revealed by the following code:
By the time the
GString is converted into a java.lang.String (its toString method is called explicitly or implicitly), each value gets written to the string. Because the logic of how to write a value can be elaborate for certain value types, this behavior can be used in advanced ways.
From Java to Groovy:
Now that you have your strings easily declared, you can have some fun with them. Because they are objects of type java.lang.String , you can call String ’s methods on them or pass them as parameters wherever a string is expected, such as for easy console output:
This line is equally valid Java and Groovy. You can also pass a literal Groovy string in single quotes:
Because this is such a common task, the GDK provides a shortened syntax:
You can drop parentheses and semicolons, because they are optional and do not help readability in this case. The resulting Groovy style boils down to:
Looking at this last line only, you cannot tell whether this is Groovy, Ruby, Perl, or one of several other line-oriented scripting languages. It may not look sophisticated, but in a way it is. It shows expressiveness—the art of revealing intent in the simplest possible way.
Listing 3.3 presents more of the mix-and-match between core Java and additional GDK capabilities. How would you judge the expressiveness of each line?
- Listing 3.3 What to do with strings
These self-explanatory examples give an impression of what is possible with strings in Groovy. If you have ever worked with other scripting languages, you may notice that a useful piece of functionality is missing from listing 3.3: changing a string in place. Groovy cannot do so because it works on instances of
java.lang.String and obeys Java’s invariant of strings being immutable.
Before you say “What a lame excuse!” here is Groovy’s answer to changing strings: Although you cannot work on String , you can still work on StringBuffer! On aStringBuffer, you can work with the << left shift operator for appending and the subscript operator for in-place assignments. Using the left shift operator on Stringreturns a StringBuffer. Here is the StringBuffer equivalent to listing 3.3:
Ps.
Groovy strings come in two flavors: plain strings and GStrings. Plain strings are instances of java.lang.String , and GStrings are instances of groovy.lang.GString .GStrings allow placeholder expressions to be resolved and evaluated at runtime. Many scripting languages have a similar feature, usually called string interpolation, but it’s more primitive than the GString feature of Groovy. Let’s start by looking at each flavor of string and how they appear in code.
Varieties of string literals:
Java allows only one way of specifying string literals: placing text in quotes “like this.” If you want to embed dynamic values within the string, you have to either call a formatting method (made easier but still far from simple in Java 1.5) or concatenate each constituent part. If you specify a string with a lot of backslashes in it (such as a Windows file name or a regular expression), your code becomes hard to read, because you have to double the backslashes. If you want a lot of text spanning several lines in the source code, you have to make each line contain a complete string (or several complete strings).
Groovy recognizes that not every use of string literals is the same, so it offers a variety of options. These are summarized in table 3.5.
The aim of each form is to specify the text data you want with the minimum of fuss. Each of the forms has a single feature that distinguishes it from the others:
- The single-quoted form
- The double-quoted form
- The triple-quoted form
- The slashy form
Groovy uses a similar mechanism for specifying special characters, such as linefeeds and tabs. In addition to the Java escapes, dollar signs can be escaped in Groovy to allow them to be easily specified without the compiler treating the literal as a GString. The full set of escaped characters is specified in table 3.6.
Note that in a double-quoted string, single quotes don’t need to be escaped, and vice versa. In other words, 'I said, "Hi."' and "don't" both do what you hope they will. For the sake of consistency, both still can be escaped in each case. Likewise, dollar signs can be escaped in single-quoted strings, even though they don’t need to be. This makes it easier to switch between the forms.
Note that Java uses single quotes for character literals, but as you have seen, Groovy cannot do so because single quotes are already used to specify strings. However, you can achieve the same as in Java when providing the type explicitly:
- char a = 'x' // or Character a = 'x'
- 'x' as char
- 'x'.toCharacter()
Working with GStrings:
GStrings are like strings with additional capabilities. They are literally declared in double quotes. What makes a double-quoted string literal a GString is the appearance of placeholders. Placeholders may appear in a full ${expression} syntax or an abbreviated $reference syntax. See the examples in listing 3.2.
- Listing 3.2 Working with GStrings
- me = 'Tarzan'
- you = 'Jane'
- line = "me $me - you $you" // Abbreviated dollar syntax
- assert line == 'me Tarzan - you Jane'
- date = new Date(0)
- out = "Year $date.year Month $date.month Day $date.date" // Extended abbreviation
- assert out == 'Year 70 Month 0 Day 1'
- out = "Date is ${date.toGMTString()} !" // Full syntax with curly braces
- assert out == 'Date is 1 Jan 1970 00:00:00 GMT !'
- // Multiple-line GString
- sql = """
- SELECT FROM MyTable
- WHERE Year = $date.year
- """
- assert sql == """
- SELECT FROM MyTable
- WHERE Year = 70
- """
- // Literal dollar sign
- out = "my 0.02\$"
- assert out == 'my 0.02$'
- me = 'Tarzan'
- you = 'Jane'
- line = "me $me - you $you"
- assert line == 'me Tarzan - you Jane'
- assert line instanceof GString
- assert line.strings[0] == 'me '
- assert line.strings[1] == ' - you '
- assert line.values[0] == 'Tarzan'
- assert line.values[1] == 'Jane'
From Java to Groovy:
Now that you have your strings easily declared, you can have some fun with them. Because they are objects of type java.lang.String , you can call String ’s methods on them or pass them as parameters wherever a string is expected, such as for easy console output:
- System.out.print("Hello Groovy!");
- System.out.print('Hello Groovy!');
- print('Hello Groovy!');
- print 'Hello Groovy!'
Listing 3.3 presents more of the mix-and-match between core Java and additional GDK capabilities. How would you judge the expressiveness of each line?
- Listing 3.3 What to do with strings
- greeting = 'Hello Groovy!'
- assert greeting.startsWith('Hello')
- assert greeting.getAt(0) == 'H'
- assert greeting[0] == 'H'
- assert greeting.indexOf('Groovy') >= 0
- assert greeting.contains('Groovy')
- assert greeting[6..11] == 'Groovy'
- assert 'Hi' + greeting - 'Hello' + '?' - '!' == 'Hi Groovy?'
- assert greeting.count('o') == 3
- assert 'x'.padLeft(3) == ' x'
- assert 'x'.padRight(3,'_') == 'x__'
- assert 'x'.center(3) == ' x '
- assert 'x' * 3 == 'xxx'
Before you say “What a lame excuse!” here is Groovy’s answer to changing strings: Although you cannot work on String , you can still work on StringBuffer! On aStringBuffer, you can work with the << left shift operator for appending and the subscript operator for in-place assignments. Using the left shift operator on Stringreturns a StringBuffer. Here is the StringBuffer equivalent to listing 3.3:
- greeting = 'Hello'
- assert greeting instanceof java.lang.String
- greeting <<= ' Groovy' // 1) Leftshift and assign at once
- assert greeting instanceof java.lang.StringBuffer
- greeting << '!' // 2) Leftshift on StringBuffer
- assert greeting.toString() == 'Hello Groovy!'
- greeting[1..4] = 'i' // Substring ‘ello’ becomes ‘i’
- assert greeting.toString() == 'Hi Groovy!'
沒有留言:
張貼留言