Groovy语法
作者:互联网
1.变量的类型
在groovy中,没有基本数据类型,只有对象类型,表面上我们定义基本数据类型,但实际都会帮我们 装箱处理:
无论定义基本数据类型还是对象类型,其实都会帮我们装成对象类型,但是对程序员来说写代码没有影响
2.变量的定义
强类型定义方式
数据类型 变量名 = 初始值
弱类型定义方式
根据值可以推断出变量的数据类型,所以类型不用显示声明,直接用def即可
def 变量名 = 初始值
用def这种弱类型定义变量可以随便改变变量类型,如果不希望别人改变数据类型用强类型,如果是你自己使用并且想要随意改变类型那么就用弱类型
3.字符串
-
字符串的常用定义方式
单引号定义方式:
def str1 = 'hi groo\nvy1' println str1 println str1.class //class java.lang.String
双引号定义方式:
def str2 = 'hi groovy2' println str2 println str2.class //class java.lang.String
三引号定义方式:
def str3 = '''hi groovy2''' println str3 println str3.class //class java.lang.String
三种方式区别:
用单引号形式定义字符串,那么字符串的格式需要自己控制,比如加:转义字符。
用三引号形式定义字符串,可以直接在字符串中定义格式,如果想要写的形式和展示的形式一样,可以在第一个三引号后加入\
def str4 = '''\ hi groovy4'''' println str4
双引号形式的字符串:可以扩展字符串
def str5 = "groovy5" def str6 = "hi ${str5}" // 拼接变量 println str6 // hi groovy5 println str6.class //class org.codehaus.groovy.runtime.GStringImpl //拼接表达式:可扩展表示融入到字符串中 def str7 = "100 + 100 = ${100+100}" println str7 // 100 + 100 = 200 println str7.class //class org.codehaus.groovy.runtime.GStringImpl
总结:双引号形式定义用的最多,因为可扩展性
-
字符串的常用方法
可直接使用java.lang.String中的方法:
def str1 = "higroovy"; println "字符串的长度为:"+ str1.length() // 字符串的长度为:8 println "字符串是否为空:"+ str1.isEmpty() // 字符串是否为空:false
使用org.codehaus.groovy.runtime.StringGroovyMethods中的方法:
def str1 = "higroovy"; println "在前后进行空格填充为指定长度"+ str1.center(10) // 在前后进行空格填充为指定长度: higroovy
Groovy中新增的操作符:
//进行比较 def str6 ="a" def str7 ="b" println str6 > str7 // false //获取字符串指定小标上的字符 def str8 = "groovy" println str8[1] //r println str8[2..3] // oo //减法操作 def str9 = "hellogroovy" def str10 = "groovy" println str9 - str10 //hello
4.流程控制
流程控制分为:顺序结构、分支结构、循环结构
-
switch-case结构
def a = 74; // 在groovy中a可以是任意类型 switch (a) { // 安装类型比较:a.class //case后面可以按照不同的类型进行判断 case 'abc': println "这是第1个分支" break case [4,7,9]://列表 println "这是第2个分支" break case 45..98://范围 println "这是第3个分支" break case Integer: println "这是第4个分支" break case BigDecimal: println "这是第5个分支" break default: println("这是第6个分支") }
-
for结构
//普通循环 for (def i = 0; i < 10; i++) { println(i) } println("--------------------") //对范围循环 for(i in 10..30){ println(i) } println("--------------------") //对列表循环 for(i in [1,2,3,4,5]){ println(i) } println("--------------------") //对map循环 for(i in [1002:"zhagnsan",2004:"lisi"]){ println(i.key+"----"+i.value) }
5.闭包
-
闭包的定义
闭包就是一段代码块,用{}括起来
def c = { println("hi groovy") }
-
闭包调用/执行
def c = { println("hi groovy") } c.call() c()//类似调用方法一样
闭包传入参数:
无参数:
// -> 前:闭包参数 -> 后:闭包体 def d = { -> println("hi groovy") } d.call()
传入单个参数:
def e = { String str -> println("hi ${str}") } e.call("groovy")
传入多个参数(用逗号隔开参数即可):
def f = { String str, int num -> println("hi ${str}, hi ${num}") } def num = 19 f.call("groovy", num);
默认参数(所有闭包都有一个默认参数,不需要你显示声明,用it接收):
def g = { println("hi ${it}") } g.call("groovy")
闭包返回值:
// 闭包一定有返回值,如果不写,就相当于返回null def c1 = { println("hi groovy") } def result = c1.call("groovy") println result
// 定义返回值: def c2 = { return "hi ${it}" } def result1 = c2.call("groovy") println result1
-
闭包常见使用常见
//与基本数据类型结合使用(for循环场景) //从2-7进行遍历:upto 2.upto(7) { println(it) } //1+2+3....+100----upto def result = 0 1.upto(100){result+=it} println(result) //输出7-2----downto 7.downto(2){println it} //输出100以内的数----times(从0开发遍历到指定的数结束) 3.times {println it} //1+2+...100----times def r =0; 101.times {r+=it} println r //如果闭关是调用方法的最后一个参数,可以直接将闭包写在外面 2.upto(7){println it}//常用 2.upto(7,{println it})//不常用
-
与字符串结合使用
//与字符串结合使用 def s = "hi groovy 2023" //遍历:如果闭包是方法的最后一个参数,可以直接将闭包写在外面 println s.each { println it } // each的返回值就是字符串本身 //找到符合条件的第一个值 def list = s.findAll { it.isNumber() } println(list.toListString()) //判断任意一位是否满足条件 println(s.any({ it.isNumber() })) //判断每一位是否满足条件 println(s.every({ it.isNumber() })) //转换大写: def list2 = s.collect({ it.toUpperCase() }) println(list2.toListString())
-
闭包中的变量
this:代表定义该闭包的类的实例对象(实例闭包)或者类本身(静态闭包)
owner:可以和this用法一样,还可以用作当闭包中嵌套闭包的时候,这时候owner就指向定义它的闭包对象
delegate:它的含义大多数情况下跟owner的含义一样,除非它被显示的修改
在Groovy脚本中定义闭包,那么this、owner、delegate指代的都是当前所在的脚本的类的对象(当前脚本编译后对应的就是一个脚本类型的类)def c1 = { println "c1-this:" + this //c1-this:ClosureTest@7502291e println "c1-owner:" + owner //c1-owner:ClosureTest@7502291e println "c1-delegate:" + delegate //c1-delegate:ClosureTest@7502291e } c1.call()
定义内部类:如果定义内部类,那么无论是闭包中还是方法中,this,onwer,delegate指代的都是所在类的对象
class Person { //定义闭包 def c2 = { println "c2-this:" + this //c2-this:Person@ebaa6cb println "c2-owner:" + owner //c2-owner:Person@ebaa6cb println "c2-delegate:" + delegate //c2-delegate:Person@ebaa6cb } //定义方法 def test() { def c3 = { println "c3-this:" + this //c3-this:Person@ebaa6cb println "c3-owner:" + owner //c3-owner:Person@ebaa6cb println "c3-delegate:" + delegate //c3-delegate:Person@ebaa6cb } c3.call() } } Person p = new Person(); // 调用内部类的闭包 p.c2.call() // 调用内部类的方法 p.test()
如果定义的内容是静态的,那么this,owner,delegate指代的就是所在的类
class Person{ //定义闭包 def static c2 = { println "c2-this:"+this //c2-this:class Person println "c2-owner:"+owner //c2-owner:class Person println "c2-delegate:"+delegate //c2-delegate:class Person } //定义方法 def static test(){ def c3 = { println "c3-this:"+this //c3-this:class Person println "c3-owner:"+owner //c3-owner:class Person println "c3-delegate:"+delegate //c3-delegate:class Person } c3.call() } } // 调用内部类的闭包 Person.c2.call() // 调用内部类的方法 Person.test()
闭包中嵌套闭包:this指代的依然是所在的类,但是onwer,delegate指代的就是嵌套闭包的闭包
def c4 = { println "c4-this:"+this //c4-this:ClosureTest@b1712f3 println "c4-owner:"+owner //c4-owner:ClosureTest@b1712f3 println "c4-delegate:"+delegate //c4-delegate:ClosureTest@b1712f3 def c5 = { println "c5-this:"+this //c5-this:ClosureTest@b1712f3 println "c5-owner:"+owner //c5-owner:ClosureTest$_run_closure1@687ef2e0 println "c5-delegate:"+delegate //c5-delegate:ClosureTest$_run_closure1@687ef2e0 } c5.call() } c4.call()
总结:无论什么情况下,this指代的都是所在类/类的对象,但是如果遇到闭包嵌套闭包,onwer和delegate指代的就是嵌套闭包的闭包
owner,delegate不同的情况:它的含义大多数情况下是跟onwer的含义一样,除非它被显示的修改class Person{} Person p = new Person() //闭包中嵌套闭包 def c4 = { println "c4-this:"+this //c4-this:ClosureTest@3d2ee678 println "c4-owner:"+owner //c4-owner:ClosureTest@3d2ee678 println "c4-delegate:"+delegate //c4-delegate:ClosureTest@3d2ee678 def c5 = { println "c5-this:"+this //c5-this:ClosureTest@3d2ee678 println "c5-owner:"+owner //c5-owner:ClosureTest$_run_closure1@1e0f9063 println "c5-delegate:"+delegate //c5-delegate:Person@53bd8fca } c5.delegate = p c5.call() } c4.call()
-
闭包委托策略
class A { String name def ac = { "name = ${name}" } String toString(){ ac.call() } } class B { String name } def a = new A(name:"丽丽") def b = new B(name:"菲菲") println a.toString() //name = 丽丽 //委托策略,修改delegate a.ac.delegate = b a.ac.resolveStrategy = Closure.DELEGATE_FIRST println a.toString() //name = 菲菲 //总结:${name}默认是从delegate取值,delegate默认和owner的值一样,委托机制也是owner_first优先,所以光改变delegate的值没用要修改委托策略为:delegate_first
6.列表
-
列表的定义
def list = new ArrayList()//java中的定义方式 //groovy中的定义ArrayList的方式 def list2 = [1, 2, 3] println list2.class println list2.size() //groovy定义数组的方式 def arr = [1, 2, 3, 4] as int[] int[] arr2 = [1, 2, 3, 4] println arr.class println arr2.class
-
列表的使用
//定义列表 def list = [1, 2, 3, 4, 5, 6] //添加操作 list.add(7) println(list.toListString()) //[1, 2, 3, 4, 5, 6, 7] list.leftShift(8) println(list.toListString()) //[1, 2, 3, 4, 5, 6, 7, 8] list << 9 println list.toListString() //[1, 2, 3, 4, 5, 6, 7, 8, 9] def newList = list + 10 println newList.toListString() //[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
//删除操作 def list2 = [1, 2, 3, 4, 5, 6] //按照索引删除操作 list2.remove(3) println(list2.toListString()) //[1, 2, 3, 5, 6] list2.removeAt(0) println(list2.toListString()) //[2, 3, 5, 6] //按照指定元素删除 list2.remove((Object) 5) println(list2.toListString()) //[2, 3, 6] list2.removeElement(6) println(list2.toListString()) //[2, 3] //按照指定条件删除元素 def list3 = [1, 2, 3, 4, 5, 6] list3.removeAll({ it % 2 == 0 }) println list3.toListString() //[1, 3, 5] //使用操作符删除 def list4 = [1, 2, 3, 4, 5, 6] def newList1 = list4 - [4, 5, 6] println newList1 //[1, 2, 3]
//排序操作 def list = [-3, -1, -5, 3, 1, 4] list.sort() //升序排列 println list //[-5, -3, -1, 1, 3, 4] //按照指定条件排序 list.sort({ num1, num2 -> num1 == num2 ? 0 : Math.abs(num1 < Math.abs(num2) ? -1 : 1) }) println list //[-5, -3, -1, 1, 3, 4] def strList = ["a", "abcd0", "aadd", "fdsad"] strList.sort({ return it.size() })//按照字符串的长度排序 println strList //[a, aadd, abcd0, fdsad]
//查找操作 def list = [-3, -1, 4, 0, 5, 2, 6] println list.find({ it % 2 == 0 })//找到列表中第一个偶数 //4 println list.findAll({ it % 2 == 0 })//找到列表中所有偶数 //[4, 0, 2, 6] println list.any({ it % 2 == 0 })//只要列表中有一个偶数,那么就返回true //true println list.every({ it % 2 == 0 })//列表中必须每个元素都是偶数的时候,才会返回ture //false println list.min()//获取最小值 //-3 println list.max()//获取最大值 //6 //做统计 println(list.count({return it>=0})) //5
7.映射
-
映射的定义
//映射的定义 //java中的hashmap def hm = new HashMap() //在groovy中定义: def map = [ '张三': 1001, '李四': 2003 ] println map.toMapString() //[张三:1001, 李四:2003]
-
映射的使用
def map = [ '张三': 1001, '李四': 2003 ] //添加元素 , 通过key添加value , 单引号是不可变字符串 , 可以省略不写 map['朱六'] = 9005 println map.toMapString() //[张三:1001, 李四:2003, 朱六:9005] map.六七 = 7001 println map.toMapString() //[张三:1001, 李四:2003, 朱六:9005, 六七:7001] map.'newMap' = ['x': 1, 'y': 2] println map.toMapString() //[张三:1001, 李四:2003, 朱六:9005, 六七:7001, newMap:[x:1, y:2]] println map.getClass() //class java.util.LinkedHashMap def map2 = [ '张三': 1001, '李四': 2003 ] as Hashtable println map2.getClass() //class java.util.Hashtable Hashtable map3 = [ '张三': 1001, '李四': 2003 ] println map3.getClass() //class java.util.Hashtable
def hm1 = [ '张三': 1001, '李四': 2003 ] hm1.each { println it.key + "---" + it.value } hm1.each { key, value -> println key + "---" + value } //带索引的遍历 hm1.eachWithIndex { Map.Entry<String, Serializable> entry, int index -> println entry.key + "---" + entry.value } hm1.eachWithIndex { key, value, index -> println key + "---" + value + "----" + index }
//映射的查找 def map = [ "张三": ["score": 68, "sex": "女"], "李四": ["score": 32, "sex": "男"], "王五": ["score": 11, "sex": "女"] ] //找到映射中第一个score大于指定数字的键值对信息 println map.find { it.value.score > 70 } //找到映射中所有score大于70的键值对信息 println map.findAll { it.value.score > 70 } println map.count { it.value.score > 60 && it.value.sex == "女" } //先查询出成绩在70以上的键值对信息,在此基础上或者key的部分 println map.findAll { it.value.score > 70 }.collect({ it.key }) //分组 println map.groupBy { it.value.socre >= 60 ? "及格" : "不及格" }
//映射的排序,按照指定的条件进行排序:按照学生的成绩排列 def map = [ "张三": ["score": 68, "sex": "女"], "李四": ["score": 32, "sex": "男"], "王五": ["score": 11, "sex": "女"] ] def newMap = map.sort { def sut1, def stu2 -> def score1 = sut1.value.score def score2 = stu2.value.score return score1 == score2 ? 0 : score1 < score2 ? 1 : -1 } println newMap
8.范围
//定义一个范围 def r = 2..5 println r.size() def r2 = 3..<8//3,4,5,6,7 println r2.size() //操作 println r[1]//通过索引获取元素 println r.contains(4) //判断是否包含某个具体的数字 println r2.from //范围开始的数字 println r2.to //范围结束的数字 //通过查看源码发现range实际就是list的一种,与列表的操作一致 //有了列表为什么还要用范围?轻量级的列表,如果定义连续范围可以使用范围 //遍历 r.each { println it } for (ele in r2) { println ele }
9.面向对象
-
类的定义和对象的定义
//类的定义和对象的定义 class Student { //属性 String name Integer age //定义构造器 Student(name, age) { this.name = name this.age = age } } //创建对象,显示编写了构造器就可以用如下方式使用构造器 def s1 = new Student("张三", 121) def s2 = new Student("lili", 12) def s3 = ["nana", 17] as Student Student s4 = ["lulu", 17] println s1.name println s2 println s3 println s4
class Student { //属性 String name Integer age } //没有显示定义构造器的时候,可以在定义对象的时候对属性进行初始化赋值 def s = new Student(name: "lili", age: 12) println s def s1 = new Student(name: "lili") println s1
//属性的取值.无论用.的方式直接取值 , 还是get / set的方式取值 , 实际底层调用都是get / set方法 class Student { //属性 String name Integer age } def s7 = new Student(name: "lili", age: 12) println "学生的姓名是:${s7.name}" println "学生的姓名是:${s7.getName()}"
-
方法的定义和调用
class Student { String name Integer age //方法的定义和调用 def m1() {//def相当于object '方法1' //groovy中,默认法中的最后一句为返回值,return可以省略 } def m2(p1, p2) {//传入多个参数用,隔开即可 "方法2:${p1}------${p2}" } static def m3() { "方法3" } } def s = new Student(name: "lili", age: 12) println s.m1() println s.m2("1", "2") println Student.m3()
//方法调用的补充 def m1(p1) { '方法1' } //调用方法的时候,()可以省略不写,后面接参数列表即可,如果有多个参数用逗号分开即可 m1("aa") m1 "bb" def m2(Closure c) { println "这是m2方法" } //调用 m2({ String name -> println name }) //如果闭包作为参数的话,闭包可以卸载外侧 m2 { String name -> println name }
-
接口
//创建接口 interface InterfaceTest { void a() def b(p1) } //在groovy中所有东西默认都睡public class Student2 implements InterfaceTest { @Override void a() { } @Override def b(Object p1) { return null } }
-
Trait
trait TraitTest { //抽象方法:abstract修饰TraitTest符必须加上 abstract void drink() //实现方法: def swim() { println "可以游泳" } } trait FlyTest { def fly() { println "可以飞行" } }
//在trait中定义抽象方法和非抽象方法,定义后就可以让类来使用(使用和接口很像,用implements实现trait) //一个类可以实现多个Trait(解决了多继承问题) class Duck implements TraitTest, FlyTest { @Override void drink() { println "游泳的时候喝到水了" } } //Trait就像抽象类和接口的结合,类实现用implements关键字来实现,可以实现多个trait
//在脚本中定义具体的对象调用方法 def d = new Duck() d.drink()//游泳的时候喝到水了 d.swim()//可以游泳 d.fly()//可以飞行
-
元编程-方法调用和拦截
元编程-方法调用和拦截
使用运行时元编程,可以在运行时截取类和接口的方法
class Person { String name Integer age def eat() { return "可以吃饭" } @Override Object invokeMethod(String name, Object args) { println "调用了invokeMethod方法" return "当前这个方法是:" + name + ",当前这个方法参数是:" + args } //如果重写了methodMissing方法,会调用methodMissing方法 def methodMissing(String name, Object args) { println "调用了methodMissing" return "当前这个方法是:" + name + ",当前这个方法参数是:" + args } }
//发现调用已有的eat方法没有问题,调用没有的方法play会直接出错,但是在groovy中可以重写方法的形式来替换不存在的方法 def p = new Person(name:"丽丽", age:12) println p.eat() println p.play()
-
元编程-metaClass
//使用运行时元变成,我们可以在运行时注入,合成类和接口的方法 //动态为person类添加sex属性: Person.metaClass.sex = "女" def p = new Person(name: "丽丽", age: 12) p.sex = "男" println p.sex //动态为person类添加方法 Person.metaClass.setNameUpperCase = { -> name.toUpperCase() } def p2 = new Person(name: "abd", age: 12) println p2.setNameUpperCase() //动态为person类添加静态方法 Person.metaClass.static.setNameLowerCase = { String name -> name.toLowerCase() } println Person.setNameLowerCase("AGSDD")
10.Groovy对Json的操作
-
Groovy自带的工具类处理json方式
class Person { String name Integer age def eat() { return "可以吃饭" } @Override Object invokeMethod(String name, Object args) { println "调用了invokeMethod方法" return "当前这个方法是:" + name + ",当前这个方法参数是:" + args } //如果重写了methodMissing方法,会调用methodMissing方法 def methodMissing(String name, Object args) { println "调用了methodMissing" return "当前这个方法是:" + name + ",当前这个方法参数是:" + args } }
package com.zt.json import com.zt.meta.Person import groovy.json.JsonOutput import groovy.json.JsonSlurper //将对象转换为json def p = new Person(name: "lili", age: 12) println JsonOutput.toJson(p) def list = [new Person(name: "lili", age: 12), new Person(name: "aaa", age: 12)] println JsonOutput.toJson(list) //打印带格式的json def jsonstr = JsonOutput.toJson(list) println JsonOutput.prettyPrint(jsonstr) //将json转换对象 def str = '{"age":11,"name":"lucky"}' def js = new JsonSlurper() def p2 = (Person) js.parseText(str) println p2 def list2 = js.parseText('[{"name":"lili","age":12},{"name":"aaa","age":12}]') println list2.class
11.Groovy对xml的操作
package com.zt.xml import groovy.xml.MarkupBuilder import groovy.xml.XmlSlurper final String xml = ''' <students> <student id="1"> <name>lili</name> </student> <student id="2"> <name>nana</name> </student> </students> ''' //解析xml def xs = new XmlSlurper() def students = xs.parseText(xml) //获取节点的值: println students.student[0].name.text() //获取属性的值 println students.student[1].@id //xml的遍历 def list = [] students.student.each { it -> list.add(it.name.text()) } println list.toListString() //生成xml def s = new StringWriter() //生成xml的核心类 def mb = new MarkupBuilder(s) //创建根节点:看上去像一个方法,但实际不是方法,只是语法长这样-伪方法 //()中传入这个节点的属性{}中写入这个节点下的节点 mb.students() { //第一个节点 student(id: "1") { name(a: "a", "张三") } student(id: "2") { name("李四") } } println s
12.Groovy对文件的操作
class Person implements Serializable { String name Integer age }
//操作普通文件 def file = new File("/Users/zt/Downloads/filetest.txt") file.eachLine { println it } //it:每行数据 println "=============" //获取文件中所有内容 println file.getText() //返回的是一个列表,将每行内容放入列表中 def list = file.readLines() println list.toListString() //读取部分内容 println file.withReader { char[] buffer = new char[2] it.read(buffer)//读取2个字符的内容 return buffer } //文件复制 def copy(String srcpath, String descpath) { //确定目标文件 def descfile = new File(descpath) if (!descfile.exists()) { //如果目标文件不存在,我们创建目标文件 descfile.createNewFile() } //复制 new File(srcpath).withReader { def lines = it.readLines() descfile.withWriter { lines.each { line -> it.append(line + "\r\n") } } return true } } println copy("/Users/zt/Downloads/filetest.txt", "/Users/zt/Downloads/filetest111aa.txt") //将对象写入文件 def saveobject(Object obj, String path) { //先将文件封装为对象 def file = new File(path) if (!file.exists()) { file.createNewFile() } file.withObjectOutputStream { it.writeObject(obj) } return true } def s = new Person(name: "aaa", age: 12) saveobject(s, "/Users/zt/Downloads/saveobject.txt") //从文件中奖对象读取出来 def readObject(String path) { def obj = null//读取的对象 //创建文件路径对应的文件对象 def file = new File(path) //判断文件不存在返回null if (file == null || !file.exists()) { return null } file.withObjectInputStream { obj = it.readObject() } return obj } def s2 = (Person) readObject("/Users/zt/Downloads/saveobject.txt") println s2.name
标签:Groovy,name,语法,Person,delegate,println,class,def 来源: https://www.cnblogs.com/ZT-666/p/16365056.html