Groovy 基础之类型与闭包

1,290 阅读7分钟

Groovy

简介

Groovy是一种DSL语言

DSL的全称是Domain Specific Language,即领域特定语言,或者直接翻译成“特定领域的语言”,其实就是这个语言不通用,只能用于特定的某个领域,俗称“小语言”。因此DSL也是语言。

  • 是一种基于JVM的敏捷性开发语言
  • 结合Python、Ruby与Smalltalk的许多强大特性
  • 可以与Java完美结合,并且可以使用Java中所有的库

特性

  • 语法上支持动态类型、闭包等新一代语言特性
  • 无缝衔接所有已经集成的Java库
  • 不仅支持面向对象编程,也支持面向过程bianc

优势

  • 一种更加敏捷的编程语言
  • 入门简单,功能强大
  • 不仅可以作为编程语言,也可以作为脚本语言

变量及定义

Groovy 变量类型分为基本类型与对象类型,定义分为强类型定义与弱类型定义 强类型定义:使用一个具体的类型,例如int x = 10 弱类型定义:使用一个def作为变量的修饰符,例如 def y = 10.9

//强类型定义的就是一个具体的类型
int x=10
double y = 10
//println x.class
//println(y.class)

//def 定义的是一个弱类型,就是object类型
def x_1 = 10
def u_1 = 23.4
def s = "cxm"
//可以重新赋值成string字符串类型
x_1 = "yif"
println(x_1.class)
println(u_1.class)
println(s.class)

String 用法

String 中使用了三种不同的引号进行定义变量

  • 单引号进行定义字符串
  • 两个单引号及双引号定义字符串可以进行扩展输出内容
  • 三个单引号进行定义字符串可以格式化输出
def name = 'this is \'a\' name'
//println name.class
//用三个单引号来进行定义string类型,可以格式化输出字符串
def thuplename = '''this is name'''
def linename = '''\
line one
line two
line three
'''
//双引号定义的字符串可以扩展
def doublename = "this is name"
def kuoname = "name"
def helloname = "hello $kuoname"
println helloname
//输出class org.codehaus.groovy.runtime.GStringImpl
println helloname.class
//println doublename
//println linename
//println thuplename.class

def sum = "the sum of 2 and 3 is Equals ${2+3}"//可以扩展任意的表达式
println sum

def result = echo(sum)
println result
//Groovy 编译器直接将GStringImpl类型转换成String 类型输出
println result.class
String echo(String msg){
    return  msg
}

String 常用API

/* ====== 字符串方法 ====== */
//1. 字符串填充
def str = "groovy hello"
//center 进行填充字符串,总共字符串长度为8 以当前字符串为中心向两边进行填充
println str.center(9, "a")
//将字符串追加到当前字符串左边
println str.padLeft(8, "a")

//2. 字符串比较
def str2 = "hello"
//使用方法
println str2.compareTo(str)
//使用操作符
println str2 > str

//3. 索引:获取字符串中的某个索引
//通过方法获取
println str2.getAt(1)
//通过中括号传入下标进行获取
println str2[1]
//传入一个范围获取字符串中的值,前后都包括
println str2[0..1]

//4. 字符串加减操作
//如果一个字符串中包含另一个字符直接相减 就获取减去的字符,不包括,则还是原来字符
println str.minus(str2)

println str.reverse()
//对字符串进行首字母大写
println str.capitalize()

循环结构使用

  • Switch 使用与Java类型,但在Groovy中又新加了许多新的声明,可以进行列表与数组或者类型的输出
  • for 循环与Java类似
//1. switch 使用
def result = 10
def x = 100
switch (x){
    case 123:
        result = 123
        break
    case '123':
        result = '123'
        break
    case [10.12,1,2,3,"hi"]://列表
        result = 'list'
        break
    case 1..23://数组
        result = 'range'
        break
    case Integer:
        result = "Integer"
        break
    case BigDecimal:
        result = "BigDecimal"
        break
    default:
        result = 'default'
        break
}
println result

//2. 对范围的for循环
def sum = 0
for(i in 0..9){
    sum += i
}
println sum

//对list的循环
sum = 0
for(i in [12,23,35,45]){
    sum += i
}
println sum

//对map进行循环
sum = 0
for(i in ["lili":3,"yif":23,"cmx":34]){
    sum += i.value
}
println sum

闭包

Groovy中有一种特殊的类型,叫做Closure,翻译过来就是闭包,这是一种类似于C语言中函数指针的东西。闭包用起来非常方便,在Groovy中,闭包作为一种特殊的数据类型而存在,闭包可以作为方法的参数和返回值,也可以作为一个变量而存在。 声明闭包: 例如:

def a = {
	//大括号中进行代码的操作输出,如果需要变量可以进行变量声明
	String name ->
}

调用闭包:

  1. 直接变量加括号进行调用
  2. 通过方法名加call方法进行调用

闭包一定有返回值,但不加return返回值为null

def clouser = {println 'hello groovy'}
//调用闭包
clouser.call()
//或者通过变量加括号进行调用
clouser()

//闭包中增加参数
def clouserresult = {String name -> println "hello ${name}"}
clouserresult.call('yif')
def name = 'ztz'
clouserresult('yif')
clouserresult(name)

//传入多个参数
def clouserresulttwo = {String tip,Integer age -> println "hello ${tip},and age is $age"}
clouserresulttwo('yif',25)

//闭包默认参数it
def test = {println "hello $it"}
test('yyy')

//闭包一定有返回值
//def returnresult = { String a -> return "hello $a"}
//不加return 也有返回值 值为 null
def returnresult = { String a -> println "hello $a"}
def cosule = returnresult('cxv')
println cosule

闭包用法

  • 与基本类型进行结合使用
  • 与String 类型进行结合使用
  • 与数据结构结合使用
  • 与文件结合使用
基本类型使用

阶乘与累加求和

// 闭包作为方法参数的最后一个,可以直接放到外面
def x = 5
println fgb(x)
//实现当前数字的阶乘
int fgb(int number){
    int result = 1
    //upto 来实现阶乘的乘法,进行循环处理
    1.upto(number,{num -> result *= num})
    return result
}

//downto 来实现阶乘
int fab(int number){
    int result = 1
    //闭包放在方法外与里面效果一样
    number.downto(1){
        num -> result *= num
    }
    return result
}
println fab(x)

//用times 来实现累加,不能用来实现阶乘,因为源码中是从0开始的
int cal(int number){
    int result = 0
    number.times {
        num -> result += num
    }
    return result
}
println cal(5)
字符串与闭包结合使用
/**
 * 字符串与闭包结合使用
 */
def string = "this is 2 to 4 result 6"
string.each {
    //multiply 将每个字符进行翻倍
    String tmp -> print tmp.multiply(2)
}
println()
//each 返回值就是调用者本身
println string.each {}

//find 查找第一个满足条件的
println string.find{
    String num -> num.isNumber()
}

//findAll 查找所以满足条件的
def list = string.findAll{
    String num -> num.isNumber()
}
println list.toListString()

//any 用来判断是否满足某个条件
def anyresult = string.any {
    String num -> num.isNumber()
}
println anyresult

//every 用来判断每一项都满足某个条件
def everyresult = string.every {
    String num -> num.isNumber()
}
println everyresult

def str = string.collect{it.toUpperCase() }
println str.toListString()

闭包三个重要变量

闭包三个重要变量this owner delegate 默认都是最近的类对象

  • 如果在类中或者方法中定义闭包,那么这三个变量输出结果都是一样的
  • 如果在闭包中嵌套一个闭包,那么这三个变量结果不一样,this还指向类对象,而owner与delegate指向的是最近的闭包对象
  • 如果人为的修改delegate指向的对象,那么owner与delegate输出结果就不一样了
  • this与owner 是不能修改的,一旦定义就明确,而delegate是可以做任意修改的
def script = {
    //这输出的是类的对象
    println "script this:" + this//代表闭包定义处的类
    println "script owner:"+owner //代表闭包定义处的类和对象
    println "script delegate:"+delegate//代表任意对象,默认与owner一致
}
script()

//定义一个内部类
class Person{
    //这输出的都是类的字节码,因为是static
    def static classClourse = {
        println "classClourse this:" + this
        println "classClourse owner:"+owner
        println "classClourse delegate:"+delegate
    }

    def static say(){
        def classClourse = {
            println "method classClourse this:" + this
            println "method classClourse owner:"+owner
            println "method classClourse delegate:"+delegate
        }
        classClourse.call()
    }
}
Person person = new Person()
//person.classClourse.call()
//person.say()
Person.classClourse.call()
Person.say()

//闭包中定义闭包
def nestClourse = {
    def innerClourse = {
        println "innerClourse this:" + this
        println "innerClourse owner:"+owner
        println "innerClourse delegate:"+delegate
    }
    innerClourse.delegate = person// 修改默认的delegate
    innerClourse.call()
}
nestClourse.call()
闭包委托策略

通过委托delegate的方式,来人为的修改原对象属性的值 委托策略Closure.DELEGATE_FIRST

  • DELEGATE_FIRST先从委托属性中寻找,没有找到再从owner中寻找;
  • DELEGATE_ONLY只从委托中寻找,没有就报错
/*
闭包委托策略
 */
class Stu{
    String name
    def printName = {" my name is $name"}
    String toString(){
        printName.call()
    }
}

class Tea{
    String name
}

def stu = new Stu(name: "yif")
def tea = new Tea(name: "fxy")
println stu.toString()
stu.printName.delegate = tea
//修改闭包委托策略,DELEGATE_FIRST先从委托属性中寻找,没有找到再从owner中寻找;DELEGATE_ONLY只从委托中寻找,没有就报错
stu.printName.resolveStrategy = Closure.DELEGATE_FIRST
//如果tea中没有这个变量name,就会从owner中寻找,找到stu中name,输出就是stu中的结果
println stu.toString()

欢迎访问个人博客 Yif博客