Variables and strings

1. 1 variable

Groovy variables have no primitives. All variables are object types. When defining a variable, both primitives and object types are converted to object types.

Here is the test code:

int x = 10
Integer y = 20
double k = 3.14
Double z = 3.1415926

println x.class
println y.class
println k.class
println z.class
Copy the code

The following output is displayed:

There are two ways to define variables in Groovy:

  • Strongly typed definition

When you define a variable, specify the type of the variable. If you want to change the value of the variable, only the value of the same type can be changed. The following are strongly typed definition variables:

int x = 1
double y = 2.0
char a = 'a'
Copy the code
  • Weak type definition

When you define a variable, you don’t need to specify the type of the variable in advance. Instead, the compiler can infer the type. This has the advantage that there is no error if you want to change the type of the variable. The following is a weak type definition:

// Use the def keyword to let the compiler infer the type
def a = 3
println a.class
a = false
println a.class
Copy the code

The following output is displayed:

As you can see, variable A was originally of type Integer. When you change the value of a, variable A becomes a Boolean type. Weakly typed variables are easy to convert from type to type.

In general, weak type definitions are recommended if the variable is used only within the module; For variables that are exposed to the outside world, a strong type definition is recommended to prevent the outside world from arbitrarily converting the type.

1. 2 Character string

Strings in Groovy correspond to Java’s String class. We can either use String directly or we can use the GString String class provided by Groovy. There are three different ways to define strings in Groovy (not including the new String() method here), as follows:

def a = 'hello world'      // Single quote definition
def b = "hello world"      // Double quotation mark definition (Java only double quotation mark definition)
def c = '''hello world'''  // Triple quotes
Copy the code

When you print out the class of these variables, you can see that the object type they belong to is class java.lang.String. Of course, there is no difference between these three ways of defining a string just like this. You can use any of them. Here are the differences:

  • The difference between single or double quotes and triple quotes is that the string defined by single or double quotes is unformatted, while the string defined by triple quotes is formatted, which means that triple quotes show all the contents of the string without the need for additional escapes.

Here’s an example:

def a = 'hello \n \' \nworld'
def b = '''hello ' world'''

println a
println b

println a.class
println b.class
Copy the code

Let’s look at the output of the code above:

As a result, if a string is defined in single quotes, “\n” or “” is needed to output a newline or some character that needs to be escaped (the same with double quotes), whereas a string defined in triple quotes can output the format as it should.

The class output above is ignored for the moment. Let’s look at the following.

  • The difference between double quotes and single or triple quotes is that double quotes can concatenate variables directly with ${}. Groovy is similar to Kotlin in this respect; If you want to concatenate variables with single and triple quotation marks, you need to concatenate variables with + signs, just like in Java.
def c = "123"
def d = "hello ${c} world"

println d
println d.class
Copy the code

Output result:

${} is Groovy’s GString. (Without concatenation, double quotes are Java strings.)

1.2.1 Common APIS for strings

  • Compares the size of strings
def str1 = 'hello'
def str2 = "Hello"

println str1 > str2 // Prints true and compares through the ASCII code table
Copy the code
  • Intercepts part of the string
def str1 = 'hello'
println str1[1.3.] // The printed result is ell
Copy the code
  • Subtract the string
def str1 = 'hello'
def str2 = "el"

println str1 - str2 // The print result is hLO
Copy the code
  • String reverse order
def str1 = 'hello'
println str1.reverse() // The print result is olleh
Copy the code
  • Uppercase
def str1 = 'hello'
println str1.capitalize() // Prints Hello
Copy the code
  • Whether all strings are numbers
def str1 = '123'
def str2 = "Hello"

println str1.isNumber() // Prints true
println str2.isNumber() // Prints false
Copy the code

Definition and use of closures

2.1 Definition and simple use of closures

One of the great things about Groovy is that it has closures that are more powerful than any other kind of language closure. Defining a closure is very simple.

  • No parameter/default parameter writing
def closure = {
    println("hello groovy")
}

closure.call()    // No arguments
closure.call(123) // Write the default argument
Copy the code

When you define a closure, if you do not define a parameter, you will have a parameter by default. You can simply pass the value into the closure when calling it.

  • There are parameters
def closure = { String name, int age ->
    println("hello $name, age is $age")
}

closure.call("Pomelo.".18)
Copy the code

2. 2 Common closure of String

  • String traversal
def str = "2 and 3 is 5"
str.each {
    // Each character is printed twice
    print it * 2
}

// Print "22 aanndd 33 iiss 55"
Copy the code
  • Find the first character that matches the condition
def str = "2 and 3 is 5"
println str.find {
    it.isNumber()
}

// The printed result is 2
Copy the code
  • Find all characters that match the criteria
def str = "2 and 3 is 5"
println str.findAll {
    it.isNumber()
}

// Print the result [2, 3, 5]
Copy the code
  • Searches for the existence of a character that matches the condition
def str1 = "2 and 3 is 5"
def str2 = 'hello'
println str1.any {
    it.isNumber()
}
// Prints true

println str2.any {
    it.isNumber()
}
// Prints false
Copy the code
  • Operates on each character in a string
def str = "Hello World"
println str.collect {
    it.toUpperCase()
}

// Print the result as [H, E, L, L, O, W, O, R, L, D]
Copy the code

2. 3 Delegation strategy for closure

2.3.1 Key variables of closures (representing the current object)

The three key variables in a closure are this, owner, and delegate, all representing the same object in the same closure.

  • This: represents the class defined by the closure
  • Owner: Represents the class or object defined by the closure
  • Delegate: Represents any object. The default object is the object pointed to by owner

1) In the same closure, both represent the same object:

def scriptClosure = {
    println this
    println owner
    println delegate
}
scriptClosure.call()
Copy the code

The printed result is:

2) Define a closure within a closure and see the difference:

// External closure
def nestClosure = {
    // Internal closure
    def innerClosure = {
        println this
        println owner
        println delegate
    }
    innerClosure.call()
}
nestClosure.call()
Copy the code

The printed result is:

As you can see from the print, this represents the object of the inner closure, while owner and delegate represent the object of the outer closure.

As you can see in the example above, owner and delegate represent the same object. Now let’s look at the differences between the two variables in other scenarios:

// Random class defined just for testing purposes
class Person {

}

Person person = new Person()
def nestClosure = {
    def innerClosure = {
        println this
        println owner
        println delegate
    }
    // Executes the closure's delegate on the Person object
    innerClosure.delegate = person
    innerClosure.call()
}
nestClosure.call()
Copy the code

The print result is as follows:

As we explained at the beginning of the explanation of the difference between this, owner, and delegate, a delegate can represent any object, whereas owner in this case can only represent an external closure.

2.3.2 Delegate strategy for closures

Let’s start with a few lines of code:

class Student {
    String name
    def pretty = {
        "My name is $name"
    }

    String toString() {
        pretty.call()
    }
}
def student = new Student(name: "Miya")
println student.toString()
Copy the code

The printed result is the expected result:

My name is Miya
Copy the code

At this point we add a few more lines to the above code, as follows:

class Student {
    String name
    def pretty = {
        "My name is $name"
    }

    String toString() {
        pretty.call()
    }
}

// Add --Teacher class
class Teacher {
    String name
}

def student = new Student(name: "Miya")
// add --teacher object
def teacher = new Teacher(name: "Youzi")
// Add -- set the delegate in student to point to teacher
student.pretty.delegate = teacher
// add -- change delegate policy priority in student to DELEGATE_FIRST
student.pretty.resolveStrategy = Closure.DELEGATE_FIRST

println student.toString()
Copy the code

Now print the result again and see:

My name is Youzi
Copy the code

The name of the teacher object is successfully printed out, and the comments are clearly written. This is the delegate strategy for the closure.