preface
Company projects also apply to the custom Gradle plugin, but I’m not involved in all the way, because is not I am responsible for another reason is that my Gradle related knowledge reserves is zero, just recently learned that, or you will forget in line with the good thought I was to learn the contents of all finishing processing, Gradle is an automatic project building tool based on The concepts of Apache Ant and Maven. It is implemented in Java. Therefore, we can consider Gradle as a lightweight Java application. Gradle uses Groovy, Kotlin, and other languages to write custom scripts. Instead of using XML configuration for Ant and Maven, Gradle greatly simplifies the configuration of project builds, making them more flexible and powerful. This article focuses on Groovy syntax. Here I recommend the Groovy tutorial, and the knowledge brain map for this article is below.
1. What is DSL
A DSL stands for domain-specific language, a computer language that focuses on an application Domain.
2. Strings
Strings in Groovy can be enclosed in single quotes (‘), double quotes (“), or triple quotes (” “). In addition, Groovy strings can span multiple lines enclosed in triple quotes, and expressions can be evaluated in double quotes using ${}, which can be omitted if the $sign is followed by only one variable.
String a = 'Hello World ! '
String b = "Hello Groovy ! ${a}"
String c = """ Hello Groovy !" ""
Copy the code
Execution Result:
Hello World !
Hello Groovy ! Hello World !
Hello
Groovy !
Copy the code
3. Data types
Basic data types
Groovy provides a variety of built-in data types. Here is a list of the data types defined in Groovy, but you can also use def when defining variables. Type derivation helps you specify data types that are no longer displayed.
-
Byte – This is used to represent byte values. For example 2.
-
Short – This is used to indicate a short integer. For example, 10.
-
Int – This is used to represent integers. For example, 1234.
-
Long – This is used to indicate a long integer. For example, 10000090.
-
Float – This is used to represent 32-bit floating point numbers. For example, 12.34.
-
Double – This is used to represent 64-bit floating point numbers that are longer decimal representations that may sometimes be required. For example, 12.3456565.
-
Char – This defines a single character literal. Such as “A”.
-
Boolean – This represents a Boolean value, which can be true or false.
-
String – These are text represented as strings. For example, “Hello World”.
Data type range
type | The scope of |
---|---|
byte | 128 to 127 |
short | 32768 to 32767 |
int | From 2147483648 to 147483647 |
long | 9223372036854775808 to + 9223372036854775807 |
float | 1.40129846432481707E-45 to 3.40282346638528860 E + 38 |
double | 4.94065645841246544E-324 D to 1.79769313486231570 E + 308D |
Wrapper type
As in Java, there are wrapper types for primitive data types as well:
- java.lang.Byte
- java.lang.Short
- java.lang.Integer
- java.lang.Long
- java.lang.Float
- java.lang.Double
You can use BigInteger and BigDecimal to support high-precision calculations
BigDecimal d = 20.48
BigInteger e = 30
Copy the code
4, methods,
Method return value
The return value of a Groovy method can be expressed as a specific data type or def, and modifiers such as public, private, and protected can be added. By default, if no visibility modifier is provided, the method is public. Groovy treats the last line of code executed as the return value by default, so you can remove the return as well
//def as return value type (automatic type derivation)
def method(){
return "Return value of Groovy method"
}
//Groovy defaults to treating the last line of code in execution as the return value
def method(def a){
if(a == 1) {1
}else{
2}}Copy the code
Method to add default values
Groovy methods have default values for parameters, and methods are called with default values defined if they are not passed
// In Groovy methods you can add default values for parameters, and the default values defined when calling method methods are not passed are used
def method(def a = 1) {if(a == 1) {1
}else{
2
}
Copy the code
I can omit the parentheses
Groovy methods can make code shorter by omitting the parentheses, such as the method method below
// Define the method
def method(int a){
print(a)
}
//
e.method(1)
// omit the parentheses
e.method 1
Copy the code
If a method takes two parameters like method(int a,int b)
def method(int a,int b){
print("$a $b")
}
e.method 1.3
Copy the code
5. Operator overloading
Groovy also has operator overloading, which is essentially calling a method in a class, in this case simply overloading the + operator
class Example {
int number
static void main(String[] args) {
Example e1 = new Example(number: 1)
Example e2 = new Example(number: 5)
print(e1 + e2)
}
// The plus method corresponds to the + operator
def plus(Example e){
number+=e.number
}
}
Copy the code
Operator overloading is very simple, which means overriding the methods that Groovy operators map to. The corresponding mapping methods can be seen in the following table
6, scope,
Groovy defines ranges. Since Range is a direct subclass of List, you can use the list-related API when manipulating Range
class Example {
static void main(String[] args) {
Range range01 = 1.10.// An example of a range
def range02 = 1.. <10// An example of exclusive scope
def range03 = 'a'.'z'// Ranges can also be composed of characters
def range04 = 10.1.// Ranges can also be sorted in descending order
def range05 = 'z'.'a'// Ranges can also be composed of characters in descending order
range01.forEach{
print(it)
}
range02.forEach{
print(it)
}
range03.forEach{
print(it)
}
range04.forEach{
print(it)
}
range05.forEach{
print(it)
}
}
}
Copy the code
7, the Map
Def Map = [‘ Shanghai ‘: ‘Shanghai ‘,’ Guangzhou ‘: ‘guangzhou’,]
def map = ['Shanghai': 'shanghai'.'guangzhou': 'guangzhou',]
// How to access map elements
defA = Mapdef b = map.get('guangzhou')
def c = map['Shanghai']
println("$a $b $c")
Copy the code
Execute export of Shanghai Guangzhou Shanghai
def map = ['Shanghai': 'shanghai'.'guangzhou': 'guangzhou',]
// Add elements
map['hefei'] = 'hefei'
// Delete elements
map.remove('Shanghai')
// Modify the elementMap. Guangzhou ='It's hot in Guangzhou'
// Iterate over the elements
map.each {
print(Key = ${it. Key} Value = ${it. Value})}// Find elements
def res = map.find {
if (it.value == 'It's hot in Guangzhou') {
return 'Guangdong needs air conditioning'
}
return 'no find city'
}
Copy the code
List and Array
List
Def list = [], or ArrayList
list = []
// Define a List
ArrayList<Integer> list = []
// Add elements
(1.10.).each {
list.add(it)
}
/ / traverse the List
list.each {
print(it)
}
// traversal with subscripts
list.eachWithIndex { int entry, int i ->
print("Value ${entry} subscript ${I}")}// Access elements by subscript
def res = list[0]
print(res)
Copy the code
Array
Integer[] array = [1,3,9,1,4,6,0,3,6,7,4] or def array = [1,3,9,1,4,6,0,3,6,7,8] as Integer[]
def array = [1.3.9.1.4.6.0.3.6.7.8] as Integer[]
// Iterate over all elements
array.each {
print(it)
}
// Get elements based on subscripts
def res = array[0]
// Find the first element that matches the condition based on the condition
def findRes = array.find {
it == 3
}
// Find all eligible elements and return a collection
def findAllList = array.findAll{
it == 3
}
// Return true as long as one condition is met
boolean isAny = array.any {
it == 3
}
// Return true if all conditions are met
boolean isEvery = array.every {
(it % 3) = =0
}
Copy the code
9, closures
You can think of a Closure as a separate block of method code, and as an object called a Closure, you can think of a Closure object as an anonymous function that takes arguments, returns values and assigns them to variables.
Using closures
Using closures is actually pretty simple, so let’s implement a little function to implement a summation function, define a method that takes a value from 0 to n, take the value and throw it to the closure
def sum = 0
pickSum(100,{
sum+=it
})
static def pickSum(n,block){
for(int i=0; i<=n; i++){ block(i) } }Copy the code
So the pickSum here is a higher-order function, you can either treat the function as an input parameter or treat the function as a return value, and in the example code you’re going through 0 to n and you’re going to pass the value to a block, and that block can be thought of as a closure, If the closure is a function at the same time also can be written as the last parameter in the code below, when the closure is a method call last argument can attach a closure on the method call, if only to pass a parameter in the closure, it can use the variable to represent the parameters, but you can also use other name
pickSum(100){
sum+=it
}
Copy the code
When you define a closure, you can either create a closure at the time of a method call or assign the closure to a variable for reuse, as in the above example, where we extract the block
def sum = 0
def block = {
sum+=it
}
pickSum(100,block)
Copy the code
For single-parameter closures you can use IT to specify variables, but for multiple parameters you must use your own names
def block = {
int a,int b -> a+b
}
def sum(int a,int b){
return block(a,b)
}
print(example.sum(1.5))
// Output result 6
Copy the code
Dynamic closures
You can determine if a closure exists, if it does use the closure otherwise use the default implementation, in the following code if a closure is defined use the closure otherwise default implementation
void sum(block){
if(block){
block()
}else{
print("Use default value")
}
}
example.sum{
print("Closure is used.")
}
example.sum()
Copy the code
Could be obtained by maximumNumberOfParameters method parameters passed in the closure, what else could be obtained through the parameterTypes closures in the data type of the refs
def res = example.sum(3){
num,rate -> num * rate
}
def res2 = example.sum(3){
it * 33
}
print(res2)
def sum(int num,Closure block){
for (param in block.parameterTypes){
println(param.name)
}
if(block.maximumNumberOfParameters == 2){
block(num,4)}else{
block(num)
}
}
Copy the code
Commissioned by the closure
Inside a closure there are three properties that can only be used inside a closure: This, owner, and Delegate. You can call this, owner, and Delegate directly. This corresponds to the class that defines the closure and, if it’s an inner class, points to the inner class. If defined in a closure, corresponding to the closure, otherwise identical to this, delegate and owner, or custom delegate pointing, the point of setting the delegate is to associate the closure with a specific object
class Example {
String name
int age
void eat(String food){
print("like eat ${food}")}@Override
String toString() {
return "name = $name age = $age"
}
static void main(String[] args) {
// Define a closure that modifies the properties of the object in the closure. You can also call object methods in the closure and access the properties and methods of the propped object
def block = {
name = 'tengfei'
age = 18
eat('KFC')
}
Example example = new Example(name: 'feifei'.age: 28)
println(example.toString())
// Associate closures with concrete objects via a delegate
block.delegate = example
block.call()
println(example.toString())
}
}
Copy the code