Groovy学习笔记-基础

时间:2023-01-16 17:41:32

作为一个近乎渣渣的七年经验程序员,回乡我的新工作竟然又是一门新语言和新框架。能学一点是一点吧。

 <hr> 

跟着Grails Getting Started-II这本书的流程学


1、创建项目

我在F盘建立了一个web目录

然后在web目录下create-app racetrack

然后Grails帮我在web目录下新建了一个项目叫racetrack

这时候我把命令行cd到racetrack目录下,输入grails run-app

程序就能运行起来了


2、创建MVC

domain就是M

命令行输入grails create-domain-class Race,grails create-domain-class Registration

    Grails帮我在domain/racetrack文件夹下创建Race.groovy,Registration.groovy文件

    我照书上给这俩类添加了一些属性


列表(list)映射(map)范围(range)
是引用其他对象的集合,前两个引用对象,后一个引用整型值。他们都能动态增长,列表通过整型值索引,映射用任意类型值索引。

列表(list)
def numbers = [11,12,13,14]
索引可以使用负数,表示从末端开始向前。
numbers[3]实质上就是numbers.getAt(3)
numbers[0..2]  //返回列表[11,12,13],表示包含边界的索引范围
numbers[0..<2]  //返回列表[11,12],表示不包含边界的索引范围

通过<<运算符可以把一个新元素追加到列表的最后
使用+运算符可以连接两个列表
numbers+[15,16]  //返回列表[11,12,13,14,15,16]
-操作符从列表中删除元素
numbers-[13]  //返回列表[11,12,14]

列表的方法
add :一个参数是在末尾追加新值,两个参数的话第一个参数指定位置
addAll:
contains:如果该列表包含指定值就返回true
get:返回当前列表中指定位置的元素值
isEmpty:如果当前列表没有元素返回true
remove:删除指定的元素,参数可以是下标,也可以是首次出现的给定元素,当元素是数值型时,不能通过元素删除,会出现越界异常(out-of-bound)
size,返回一个整数,表示元素个数

以下是GDK新增
flatten:使当前列表元素形式一致并返回一个新列表
getAt:和get一个样,这个是GDK新增的,区别只是这个能复数索引,能通过范围返回新列表
intersect:返回一个新列表,其值为原始列表和输入列表的所有元素
leftShift:重载左移运算符,提供一个像列表添加新值得简单方法
minus:生成一个新列表,元素由原始列表中那些不包含在参数collection中的值组成
plus:生成一个新列表,参数可以是值也可以是列表
pop:删除当前列表中最后一个值元素
putAt:赋值语句支持下标运算符
reverse:返回原列表倒序
sort:返回原始列表排序副本

映射(map)
一种引用对象的无序集合,映射中元素可以根据关键字访问,关键字可以是任意类型,映射的值可以为空。
范例:
['Ken':'Barclay','John':'Savage']          姓/名集合
[4:[2],6:[3,2],12:[6,4,3,2]]                       整形关键字及其约数列表
[:]                                                          空映射
如果关键字是变量名,就解释成String
def x=1
def y=2
def m = [x : y , y : x]
于是m就是映射:
m=['x' : 2, 'y' : 1]

映射中增加一个元素如下
library['Sally']=['Basic']

映射的方法:
containsKey:
get:根据Key找Value,第二个参数可选,可以放默认值,如果没有找到对应的key则返回默认值,没放默认值得话,没找到返回空。
keySet:返回当前映射的一组关键字(Set类型),可以用来遍历映射。
getAt:
put:第一个参数放Key,第二个参数放Value,都是对象类型。
size:
values:返回当前映射中所有值得结合,类型是Collection

范围(range)
范围是表达特定序列值得简略方法。通过雪烈中第一个值和最后一个值表示,范围可以是倒序,也可以用<表示不包含边界
1900..1999           //20世纪包含边界
2000..<2100        //21世纪(不包含边界)
'A'..'D'                 //A,B,C,D
10..1                    //10,9,....,1
'Z'.. 'X'                // Z,Y和X

范围可以根据下标访问
def reversedTen = 10..1
reversedTen[2]                          //8

这个例子表示范围的升序降序可以通过整型表达式表示:
def start = 10
def finish = 20
start..finish + 1         //[10~21]

范围的方法:
contains:如果当前范围包含元素则返回true
get:返回当前范围中给定位置的元素
getFrom/getTo:获取当前范围中下标最大最小的元素
isReverse:当前范围是否为逆序
size:
subList:取之间的值,不包含toIndex



1.定义一个方法
Groovy中定义一个方法关键字还是def
def greetings(){
    print "Hello and welcome"
}
greetings()

2.在一行中使用多个语句用分号分开
def greetings(){
    print "Hello e"; print "and welcome"
}
greetings()

3.方法参数
Groovy是弱类型语言,所以方法签名中的参数没有类型,只有名称
def greetings(name){
    print "Hello e"; print "and welcome ${name}"
}
greetings("John")

多个参数用逗号分隔,可以有默认值,
def someMethod(para1,para2 = 0,para3 = 0 ){
}

4.方法返回值
在方法签名上没有体现,在方法体重直接用retrun返回就可以了

5.隐式返回值
其实 就是return语句是可以不写的,最后一句语句的值就是返回值

6.参数传递
Groovy没有引用传递和值传递之分,只有传值方式,也就是java的值传递。
也就是说在方法内部修改变量,外侧的变量不受影响。
集合(列表、映射、范围也可以作为方法的参数和返回值)

7.作用域
在方法内定义的变量,只能在方法内使用,方法外部不能访问。
另外Groovy入门经典这本书说,在方法内部不能访问方法外的变量,但是,在Groovy2.4.3环境下亲测是可以访问的。大概老版本不能访问吧。

8.断言
跟java一样也是assert()方法,比如 assert('1'=='1')  
如果断言为真,不输出任何结果,如果断言为假则抛出一个异常
类似这样

|
          false


 at test.run(test.groovy:6)

8.while语句
直到括号里面的值为false时终止循环
def LIMIT =10
def count =1
println 'Start'
while(count <=LIMIT){
    println "count:${count}"
    count++
}
println 'Done'

9.for语句
Groovy的for语句只能使用in关键字,in前面是值,in后面可以是列表、映射、范围、字符串
def LIMIT =10

println 'Start'
for(count in 1..LIMIT){
    println "count:${count}"
    count++
}
println 'Done'
以上的意思就是从1开始循环到10,确实代码量变少,功能更清晰了。

10.if语句
 Groovy的if语句和javaScript,java一模一样

11.switch语句
也和 javaScript,java一模一样,只是case中可以是列表、映射、范围、字符串,正则表达式
当然列表的时候只要一个符合就可以,字符串要整句匹配上才可以。

12.break和continue语句
 与java没有区别

简而言之,Groovy闭包就是将方法定义成变量。

入门经典对Groovy的闭包定义的很清晰且深入浅出,原文摘录如下
Groovy闭包是以后总表示可执行代码块的方法。闭包也是对象,可以像方法一样传递参数。由于闭包是代码块,因此也可以在需要时执行。像方法一样,在定义的过程中,闭包可以使用一个或者多个参数。闭包的一个重要的特有属性就是,它们可以访问属性信息。这就意味着在声明闭包之后,闭包可以使用并修改其作用域内的所有变量值。

闭包最常用的用途是处理集合,比如可以遍历没然后将闭包应用到每个元素上,闭包是Groovy能简化脚本开发的一个重要原因。

闭包及其调用方法(call是可以省略的
def clos = {param -> println "Heool ${param}"}
clos.call('word');
clos('again')

param ->也是可以省略的,称为隐参数用it代替,显然只有一个参数的时候才能这样
def greeting = 'Hello'
def clos = { println "${greeting} ${it}"}
clos.call('word')
greeting = 'Welcome'
clos.call('word')

通过闭包改变方法外属性值
def greeting = 'Hello'
def clos = {param -> println "${greeting} ${param}"}
clos.call('word')
greeting = 'Welcome'
clos.call('word')

输出是
Hello word
Welcome word
这里做了个是实验,江闭包放到最后,发现报错了,可见闭包跟javascript的对象话的方法不一样,javascript的方法对象,总是首先被读入内存的。

将闭包作为方法参数
def greeting = 'Hello'
def clos = {param -> println "${greeting} ${param}"}
clos.call('word')

greeting = 'Welcome'
clos.call('word')

def demo(clo){
    def greeting ='bonjour'
    clo.call('Ken')
}

demo(clos)

如果方法调用的最后一个参数是闭包,可以把闭包写到括号后面、
demo(clos)
demo() 
clos
def greeting = 'Hello'
def clos = {param -> println "${greeting} ${param}"}

def demo(clo){
    def greeting ='Bonjour'
    clo.call('Ken')
}

//demo()clos
demo(){param -> println "Welcom ${param}"}
demo clos
demo {param -> println "Welcom ${param}"}

最后两句代码调用demo方法并江必报作为实参,倒数第二句代码调用闭包对象,倒数第一句代码调用 闭包自面值,这两种方法都省略了方法的括号

注释掉那句代码运行时报错,对比一下后一句,可以看出当有括号时,只能使用闭包自面值,不能调用闭包对象。

使用闭包求阶乘
def factorial = 1
1.upto(2){num -> factorial *= num}
println "Factorial(5):${factorial}"
println "${1.upto(5){}}"

结果是
Factorial(5):120
null

这里每次调用 upto方法时都从字面值1开始,一直循环到给定参数5后面的闭包也就执行了五次

闭包用在集合和字符串上
[1,2,3,4].each{print it}
打印结果是
1234
Result: [1, 2, 3, 4]

Groovy有很多方法是利用闭包的,我就不一一写了。


举个栗子
class Account{
    def number
    def balance
   
    def credit(amount){
        balance += amount
    }
   
    def debit(amount){
        if(balance >= amount)
            balance = amount
    }
   
    def display(){
        println "Account ${number} with balance ${balance}"
    }
}

def acc = new Account(number:'ABC123',balance:1200)
acc.display()
acc.credit(200)
acc.display()

输出是:

Account ABC123 with balance 1200
Account ABC123 with balance 1400

除了初始化类的方式之外,和java语法貌似没有什么不同。可以想象实现方式一定是java的getter和setter方法。

构造器
Groovy中也可以显式的声明构造方法,用来初始化类的属性。
构造器和方法的最大区别在与构造器名和类名相同。
class Account{
    def number
    def balance
   
    def Account(number ,balance){
        this.number = number
        this.balance = balance
    }
   
    def credit(amount){
        balance += amount
    }
   
    def debit(amount){
        if(balance >= amount)
            balance = amount
    }
   
    def display(){
        println "Account ${number} with balance ${balance}"
    }
}

//def acc = new Account(number:'ABC123',balance:1200)
def acc = new Account('ABC123',1200)
acc.display()
acc.credit(200)
acc.display()

这样一来Groovy的类同java的类就非常像了。