Getting started with Gradle-Grovvy language foundation

 

Why learn Grovvy

The official recommended language of Gradle is Groovy, which is a jvm language. If you want to perform plug-in modules, hot repairs, complex construction systems, etc., you need a little understanding of Groovy. You don't need to learn the details of Groovvy. Generally, the benefits are too great. Low, like bloggers only use Gradle to build SpringBoot, and the main project language is not Groovy.

There are quite a few Gradle users who have no basic concepts at all. Whenever they encounter a need or problem, they need to find it online. This is a misunderstanding.

Gradle is not just a configuration script, I personally think that behind it is a combination of two languages:

Groovy Language + Gradle DSL

The DSL part can also be expanded. If you are using the Android ecosystem, there will also be Android DSL, a total of three.

The full name of DSL is Domain Specific Language, that is, "domain specific language", which means that this language is not universal and can only be used in a specific domain, commonly known as "small language". So DSL is also a language.

If you don't understand at least these two languages, there may be obstacles to basic Gradle usage. At this time, random searching or memorizing from the Internet is actually a huge time cost burden. It's better to learn them as languages, and you don't need to set them hard, because languages ​​are documented, we only need to learn grammar and then check the document.

The relationship between Groovy and Java

Groovy is a JVM language, it is finally compiled into a class file and then executed on the JVM, so the features of the Java language Groovy support, can mix Java and Groovy is its feature, in contrast, Gradle supports the other same Kotlin, which is a jvm language, cannot be mixed.

What are the advantages of using Groovy? Simply put, Groovy provides a lot of syntactic sugar and closure features that allow you to achieve the same functions as Java with less code. For example, to parse xml files, Groovy is very convenient, only a few lines of code can be done, and if you use Java, you need dozens of lines of code. This feature is very suitable for designing and constructing software files. Imagine a situation where Maven is abandoned and used to write a construction system directly in Java. Technically, it can be done, but it is difficult to manage.

Since Groovy is so concise, why JAVA is not learned and there is no free lunch in the world. Of course, Groovy's execution speed is much slower. This is a physical limitation of programming linguistics. It is used for writing construction files or as a glue language.

Announcement of Groovy's Variables and Methods

Groovy declares variables and methods through the def keyword, for example:

def x = 1;
def y = "hello world";
def int c = 1;
 
def hello() {
   println ("hello world");
   return 1;
}

task taskA {
    println(hello()
)
}

Below is the code of a task block, which is Gradle DSL, which can be used to execute Groovy programs. In the example, a taskA is used to execute Groovy code. Create a build.gradle file, paste the code, and enter gradle -q taskA to see the execution result. There is no need to install the Groovy SDK, we just use Gradle.

This example outputs two lines of results:

hello world
1

In Groovy, many things can be omitted, such as:

  • Semicolon after statement
  • Variable type and method return value
  • Parentheses when calling methods
  • Return on the last line

So the above code can also be written as:

def hello() {
   println ("hello world");
   return 1;
}

def hello(String message) {
   println message; // ignore parentheses brackets
   1;        // ignore return
}

def hello2(message) { // ignore type
   println message;
   return 1;        // can not ignore return
   println "Done"
}

task taskA {
    println hello("hello world")
    println hello2("hello world 2")
}

summary

  • Types can be weakened, and all types can be dynamically inferred, but Groovy is still a strongly typed language, and errors will still be reported if types do not match.
  • Many things can be omitted, so there is no compulsory writing that you like.
  • The annotation method in Groovy is the same as in Java.

Groovy data types

Groovy data types:

  • Basic data types of Java
  • Java objects
  • Closure
  • Enhanced List, Map and other container types
  • Enhanced File, Stream and other IO types
  • Types can be declared explicitly or declared with def. Types declared with def will be inferred by Groovy.

It should be noted that in Gradle, the default modifier for objects is public. The following mainly talk about String, closure, collection, IO, etc. The basic types of Java are exactly the same as objects, so skip it.

String

Groovy's string has its own characteristics in splicing, such as:

def funcA() {
    def a = 1
    def b = "hello"
    def c = "a=${a}, b=${b}"
    println c
}

task taskA {
    funcA()
}

result:

a=1, b=hello

Closure

There is a special type in Groovy called Closure, which is translated as closure, which is similar to a function pointer in C language. Closures are very convenient to use. In Groovy, closures exist as a special data type. Closures can be used as method parameters and return values, or as a variable.

Announcement method

{ parameters ->
   code
}

Closure can have return values ​​and parameters, or none. example:

def clos = { int a, String b ->
    println "a=${a}, b=${b}"
}

def clos2 = { a, b ->
    println "a=${a}, b=${b}"
}

def clos3 = { a, b ->
    a + b
}

task taskA {
    clos(10, "rojar")
    clos2(20, "rojar")
    println clos3(10, 20)
}

Output:

a=10, b=rojar
a=20, b=rojar
30

In addition, if the Closure closure does not specify parameters, then it will have an implicit parameter it, for example:

def clos4 = {
    println "a=${it}"
}

Output:

a=100

One of the difficulties of Closure is how to know its functions and parameters. Although the commonly used VS Code has plug-in language support, there is no way to quickly display detailed instructions. There is no other way, but to manually query the official Groovy documents:

http://www.groovy-lang.org/api.html

Groovy JDK API Documentation http://docs.groovy-lang.org/latest/html/groovy-jdk/index-all.html

A specific example will be combined later to illustrate how to check the file.

List and Map

Groovy enhances the container classes in Java, such as List, Map, Set, etc.

Example of List:

def clos5 = {
    def test = [10, "rojar", true]
    test[1] = "smith"
    println test[0]
    println test[1]
    test << 200
    println test[3]
    println test.size
}

task taskA {
    clos5()
}

Output:

10
smith
200
4

You can see the wonderful operator << in the code of the List, which means adding a new element to the List, which can also be found in the file.

Open the Groovy JDK API Documentation, check the initial letter of L, you will see:

List - Interface in java.util

After searching the page for leftShit, click in and you will see:

There are many containers that have leftShift operation. Only by querying the file can you know how to use it correctly.

Example of Map:

def clos6 = {
    def emptyMap = [:]
    def test = ["id":1, "name":"rojar", "isMale":true]
    test["id"] = 2
    test.id = 200
    println test.id
    println test.isMale
}

task taskA {
    clos6()
}

Output:

200
true

As you can see, Groovy is obviously much more concise to manipulate List and Map than Java.

By the way, explain how to determine the parameters of the closure with the help of Map. For example, if we want to traverse a Map, by looking at the document, we find that it has two methods, which seem to be related to traversal:

As you can see, the parameters of the two each method are both a Closure, so how do you know the parameters of the closure? Still need to look at the file, click each to see the details.

It can be seen from the file that the parameters of this Closure closure are of variable length. If the closure we pass is a parameter, then it takes entry as a parameter; if the closure we pass is 2 parameters, then it takes the key and value As a parameter.

Try to traverse according to the file:

def clos7 = {
    def emptyMap = [:]
    def test = ["id":1, "name":"rojar", "isMale":true]
 
    test.each { key, value ->
       println "two parameters, find [${key} : ${value}]"
    }
 
    test.each {
       println "one parameter, find [${it.key} : ${it.value}]"
    }
}

task taskA {
    clos7()
}

Output:

two parameters, find [id : 1]
two parameters, find [name : rojar]
two parameters, find [isMale : true]
one parameter, find [id : 1]
one parameter, find [name : rojar]
one parameter, find [isMale : true]

The other eachWithIndex is similar, you can try it yourself. Since Index is used, you can do some operations such as skipping numbers.

From this example, I know that if I don’t learn how to read official documents according to my needs, and search google randomly, can I find just the right teaching or discussion every time? Can you be dead back?

Enhanced IO

In Groovy, file access is simpler than Java, whether it is a normal file or an xml file. Check the document first:

According to the eachLine method of File, we can write the following traversal code. You can see that the eachLine method also supports 1 or 2 parameters. What do these two parameters mean, you need to learn to read files, blindly from the Internet Looking for examples above, it is inefficient and painful:

def clos8 = {
    def file = new File("somefile.txt")
    println "read file using two parameters"
    file.eachLine { line, lineNo ->
       println "${lineNo} ${line}"
    }
 
    println "read file using one parameter"
    file.eachLine { line ->
       println "${line}"
    }
}

task taskA {
    clos8()
}

In addition to eachLine, File also provides a lot of methods that Java doesn't have. Simply browse through which methods are available, and then check them when you need them. No need to learn about them.

XML reading and writing example:

<xml>
    <resources>
       <attr name="first_name">Rojar</attr>
       <attr name="last_name">Smith</attr>
    </resources>
</xml>

Code:

def clos9 = {
    def xml = new XmlParser().parse(new File("somefile.xml"))
    println xml['resources'].attr[0].@name
    // Read attribute
    println xml['resources'].attr[1].text()
   // Read context
}

task taskA {
    clos9()
}

Output:

first_name
Smith

Groovy other features

There are also some common and noteworthy features that need to be learned. Some features may shorten the code but have dyslexia, so it is recommended not to use them.

Class is a first-class citizen

In Groovy, you can omit .class for all Class types, such as:

func(File.class)
func(File) // The same as before.

def func(Class clazz) {
}

Automatically generate Getter and Setter

Getter/Setter and properties are automatically generated by default, such as:

class Person {
   private String name
   String getName() { return name }
   void setName(String name) { this.name = name }
}

// The same as before.
class Person {
   String name
}

The reverse is also possible, as long as there is Getter/Setter, then it has implicit properties.

with operator

When operating on the same object, you can use with, for example:

Person p = new Person()
p.id = 1
p.name = "rojar"

// The same as before.
Person p = new Person() 
p.with {
   id = 1
   name = "rojar"
}

Judge whether it is true

The data length will be automatically checked when judging whether it is true:

if (name != null && name.length > 0) {}
 
// The same as before
if (name) {}

Concise ternary expression

It can be more simplified when judging whether it is null:

def result = name != null ? name : "unknown"

// reduce name
def result = name ?: "unknown"

assertion

Use assert to set the assertion. When the condition of the assertion is false, the program will throw an exception:

def check(String name) {
   // name non-null and non-empty according to Groovy Truth
   assert name
   // safe navigation + Groovy Truth to check
   assert name?.size() > 5
}

switch method

Compared with the switch provided by Java, it is more flexible and can support more judgment types at the same time:

def x = 20.21
def result = ""
switch (x) {
   case "foo": result = "found foo"
   // lets fall through
   case "bar": result += "bar"
   case [4, 5, 6, 'inList']: result = "list"
   break
   case 12..30: result = "range"
   break
   case Integer: result = "integer"
   break
   case Number: result = "number"
   break
   case { it > 3 }: result = "number > 3"
   break
   default: result = "default"
}
assert result == "number"

== and equals

== is equivalent to Java's equals. If you need to compare whether two objects are the same, you need to use .is():

Object a = new Object()
Object b = a.clone()
 
assert a == b
assert !a.is(b

Concluding remarks

I believe that Groovy has learned this, and most of the Groovy parts used in Gradle should be able to get started.

Comments

Popular posts from this blog

Gradle configuration Spring multi-project test

Linux uses NVM to manage Nodejs