经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Groovy » 查看文章
groovy常用语法及实战
来源:cnblogs  作者:GisFe  时间:2019/8/7 8:49:55  对本文有异议

groovy语言简介

  • 一种基于JVM的敏捷开发语言,作为编程语言可编译成java字节码,也可以作为脚本语言解释执行。
  • 结合了Python、Ruby和Smalltalk的许多强大的特性
  • 支持面向对象编程也支持面向过程编程
  • 支持动态类型,闭包等语言特性
  • 无缝集成所有已经存在的java类库

groovy环境搭建

参考官网groovy环境搭建

groovy的hello world

在groovy语言中,如下两种写法效果完全相同

版本1:

  1. class HelloGroovy {
  2. public static void main(String[] args) {
  3. System.out.println("hello groovy!");
  4. }
  5. }

版本2:

  1. print "hello groovy"

版本2看起来是脚本,其实是编译器帮我们变成了class,版本2脚本对应的class反编译为如下代码:

  1. import groovy.lang.Binding;
  2. import groovy.lang.Script;
  3. import org.codehaus.groovy.runtime.InvokerHelper;
  4. public class HelloGroovy extends Script {
  5. public HelloGroovy() {
  6. }
  7. public HelloGroovy(Binding context) {
  8. super(context);
  9. }
  10. public static void main(String... args) {
  11. InvokerHelper.class.invoke<invokedynamic>(InvokerHelper.class, HelloGroovy.class, args);
  12. }
  13. public Object run() {
  14. return this.invoke<invokedynamic>(this, "hello groovy");
  15. }
  16. }

我们直观感受一个是编译语言,一个是脚本语言,但其实最后都是编译执行的。

groovy基础语法

变量

变量类型:全部为对象类型,不存在基本类型,基本类型的定义都会被转化为对象类型。

  1. package variable
  2. int x = 10
  3. println x.class
  4. double y = 3.14
  5. println y.class

输出为:

  1. class java.lang.Integer
  2. class java.lang.Double

变量定义:强类型和弱类型def定义

  1. def x_1 = 3.1415
  2. println x_1.class

def定义时,会根据值的类型将变量转化为对应类型,重新赋值为其他数据类型的值,则变量类型也会变为其他数据类型

建议:内部使用的变量建议使用def定义,而提供给外部程序使用的变量,则建议使用强类型

字符串

StringGString

字符串使用单引号、双引号和三个单引号定义都等同为String,区别:

  • 单引号没有格式,格式需要转义,比如换行需要拼接;三个单引号可以直接指定格式
  • 单引号不能引入扩展表达式,双引号可以在字符串中引入扩展表达式。如果双引号存在扩展表达式,类型则为GString
  1. //def name = 'a single \'a\'string'
  2. //println name.class
  3.  
  4. def thupleName = '''line one
  5. line two
  6. line three
  7. '''
  8. //println thupleName
  9. def doubleName = "this a common String"
  10. //println doubleName.class
  11.  
  12. def name = "Qndroid"
  13. def sayHello = "Hello: ${name}"
  14. //println sayHello
  15. //println sayHello.class
  16.  
  17. def sum = "the sum of 2 and 3 equals ${2 + 3}" //可扩展做任意的表达式
  18. //println sum

String方法来源:

java.lang.String,常用java类型,比较熟悉了

DefaultGroovyMethods,groovy所有类型都有的方法

StringGroovyMethods,继承DefaultGroovyMethods,有普通类型的参数和闭包类型的参数

  1. package org.codehaus.groovy.runtime;
  2. ...
  3. public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
  4. ...

groovy新增的部分string方法如下:

  1. /* ==================字符串的方法=================== */
  2. def str = "groovy Hello"
  3. //println str.center(8)
  4. //println str.padLeft(8, 'a')
  5. def str2 = 'Hello'
  6. //println str > str2
  7. //println str[0]
  8. //println str[0..1]
  9. //println str - str2
  10. //println str.reverse()
  11. //println str.capitalize()

逻辑控制

  1. //对范围的for循环
  2. def sum = 0
  3. for (i in 0..9) {
  4. sum += i
  5. }
  6. //println sum
  7. sum = 0
  8. /**
  9. * 对List的循环
  10. */
  11. for (i in [1, 2, 3, 4, 5, 6, 7, 8, 9]) {
  12. sum += i
  13. }
  14. /**
  15. * 对Map进行循环
  16. */
  17. for (i in ['lili': 1, 'luck': 2, 'xiaoming': 3]) {
  18. sum += i.value
  19. }

方法调用

方法如果只有一个参数,可以省略()

groovy闭包

闭包定义、调用和返回值

闭包就是一段代码块,代码块用{ }表示

  1. def clouser = { println "hello groovy!" }
  2. //闭包调用
  3. //clouser.call()
  4. clouser()

闭包普通参数和隐式参数

->之前就是参数部分,可以为空(没有参数)

  1. //普通参数
  2. def clouser = { String name -> println "hello ${name}!" }
  3. //闭包调用
  4. //clouser.call()def name = 'groovy!'
  5. clouser(name)
  6. //多个参数
  7. def clouser = {String name, int age ->
  8. println "hello ${name}, My age is ${age}"
  9. }
  10. def name = 'groovy!'
  11. clouser(name,4)
  12. //默认隐式参数 it
  13. def clouser = { println "hello ${it}"}
  14. def name = 'groovy!'
  15. clouser(name)

 

闭包的返回值

如果有return语句,则返回对应值,如果没有return语句,则返回null

闭包的用法

与基本类型的结合,闭包参数需要查看源码,看需要传入的参数

  1. int x = fab(5)
  2. println x
  3. //用来求指点number的阶乘
  4. int fab(int number) {
  5. int result = 1
  6. 1.upto(number, {num -> result *= num})
  7. return result
  8. }
  9. //结果为120
  10. int cal(int number) {
  11. int result = 0
  12. number.times {
  13. num -> result += num
  14. }
  15. return result
  16. }

 

upto源码

  1. public static void upto(Number self, Number to, @ClosureParams(FirstParam.class) Closure closure) {
  2. int self1 = self.intValue();
  3. int to1 = to.intValue();
  4. if (self1 <= to1) {
  5. for (int i = self1; i <= to1; i++) {
  6. closure.call(i);
  7. }
  8. } else
  9. throw new GroovyRuntimeException("The argument (" + to +
  10. ") to upto() cannot be less than the value (" + self + ") it's called on.");
  11. }

 

 

 

与String结合

  1. String str = 'the 2 and 3 is 5'
  2. //each的遍历,返回值为本身
  3. str.each {
  4. String temp -> print temp
  5. }
  6. //find 来查找符合条件的第一个
  7. str.find {
  8. String s-> s.isNumber()
  9. }

 

find源码

  1. public static Object find(Object self, Closure closure) {
  2. BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
  3. for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
  4. Object value = iter.next();
  5. if (bcw.call(value)) {
  6. return value;
  7. }
  8. }
  9. return null;
  10. } 

与数据结构结合

与文件等结合

闭包进阶

闭包关键变量this

闭包关键变量owner

闭包关键变量delegate

  1. /**
  2. * 闭包的三个重要变量:this,owner,delegate
  3. */
  4. def scriptClouser = {
  5. println "scriptClouser this:" + this //闭包定义处的类
  6. println "scriptClouser owner:" + owner //闭包定义处的类或者对象
  7. println "scriptClouser delegate:" + delegate //任意对象,默认为owner一致
  8. }
  9. scriptClouser.call()
  10. //this为闭包定义处的类,
  11. //定义了一个内部类,在脚本类中
  12. class Person {
  13. def static classClouser = {
  14. println "classClouser this:" + this
  15. println "classClouser owner:" + owner
  16. println "classClouser delegate:" + delegate
  17. }
  18. def static say() {
  19. def classClouser = {
  20. println "methodClassClouser this:" + this
  21. println "methodClassClouser owner:" + owner
  22. println "methodClassClouser delegate:" + delegate
  23. }
  24. classClouser.call()
  25. }
  26. }
  27. Person.classClouser.call()
  28. Person.say()
  29. //闭包中定义一个闭包
  30. def nestClouser = {
  31. def innerClouser = {
  32. println "innerClouser this:" + this
  33. println "innerClouser owner:" + owner
  34. println "innerClouser delegate:" + delegate
  35. }
  36. innerClouser.call()
  37. }
  38. nestClouser.call()

 

闭包的委托策略

  1. /**
  2. * 闭包的委托策略
  3. */
  4. class Student {
  5. String name
  6. def pretty = { "My name is ${name}"}
  7. String toString() {
  8. pretty.call()
  9. }
  10. }
  11. class Teacher {
  12. String name
  13. }
  14. def stu = new Student('Sarash')
  15. def tea = new Teacher('Ondroid')
  16. stu.pretty.delegate = tea
  17. stu.pretty.resolveStrategy = Closure.DELEGATE_FIRST
  18. println stu.toString() 

常见数据结构使用

列表的定义

  1. //def list = new ArrayList() //java的定义方式
  2. def list = [1, 2, 3, 4, 5]
  3. println list.class
  4. println list.size()
  5. def array = [1, 2, 3, 4, 5] as int[]
  6. int[] array2 = [1, 2, 3, 4, 5]

 

列表的操作:原理为操作ArrayList

映射map的定义

  1. //def map = new HashMap()
  2. def colors = [red : 'ff0000',
  3. green: '00ff00',
  4. blue : '0000ff']
  5. //索引方式
  6. //println colors['red']
  7. //println colors.red
  8. colors.blue
  9. //添加元素
  10. //colors.yellow = 'ffff00'
  11. colors.complex = [a: 1, b: 2]
  12. //println colors.getClass()

 

范围range的定义和使用

  1. def range = 1..10
  2. //println range[0]
  3. //println range.contains(10)
  4. println range.from
  5. println range.to
  6. //遍历
  7. range.each {
  8. // println it
  9. }
  10. for (i in range) {
  11. // println i
  12. }
  13. def result = getGrade(75)
  14. println result
  15. def getGrade(Number number) {
  16. def result
  17. switch (number) {
  18. case 0..<60:
  19. result = '不及格'
  20. break
  21. case 60..<70:
  22. result = '及格'
  23. break
  24. case 70..<80:
  25. result = '良好'
  26. break
  27. case 80..100:
  28. result = '优秀'
  29. break
  30. }
  31. return result
  32. }

 

面向对象特性

类、接口等的定义和使用

类:

  1. groovy中默认都是public
  2. 无论你是直接还是调用get/set,最终都是调用get/set

接口:

接口中不许定义非public的方法

Trait:

和接口一样,唯一不同是可以有默认实现

元编程

方法寻找流程

  1. 类中是否有此方法
  2. MetaClass中是否有此方法
  3. 是否重写了methodMissing()
  4. 是否重写了InvokeMathod()
  5. Throw MissingMethodException

为类动态的添加一个属性

Person.metaClass.sex = 'male'

为类动态的添加方法

Person.metaClass.nameUpperCase = { -> sex.toUpperCase()}

为类动态的添加静态方法

Person.metaClass.static.createPerson = {}

高级用法实战

json文件处理及json,model互转

代码样例:

  1. import groovy.json.JsonOutput
  2. import groovy.json.JsonSlurper
  3. import objectorention.Person
  4. //def json = JsonOutput.toJson(list)
  5. def reponse =
  6. getNetworkData(
  7. 'http://xxx.json')
  8. println reponse.data.head.name
  9. def getNetworkData(String url) {
  10. //发送http请求---完全是使用java库
  11. def connection = new URL(url).openConnection()
  12. connection.setRequestMethod('GET')
  13. connection.connect()
  14. def response = connection.content.text
  15. //将json转化为实体对象
  16. def jsonSluper = new JsonSlurper()
  17. return jsonSluper.parseText(response)
  18. } 

xml文件读取

代码样例:

  1. import groovy.xml.MarkupBuilder
  2. final String xml = '''
  3. <response version-api="2.0">
  4. <value>
  5. <books id="1" classification="android">
  6. <book available="20" id="1">
  7. <title>疯狂Android讲义</title>
  8. <author id="1">李刚</author>
  9. </book>
  10. <book available="14" id="2">
  11. <title>第一行代码</title>
  12. <author id="2">郭林</author>
  13. </book>
  14. <book available="13" id="3">
  15. <title>Android开发艺术探索</title>
  16. <author id="3">任玉刚</author>
  17. </book>
  18. <book available="5" id="4">
  19. <title>Android源码设计模式</title>
  20. <author id="4">何红辉</author>
  21. </book>
  22. </books>
  23. <books id="2" classification="web">
  24. <book available="10" id="1">
  25. <title>Vue从入门到精通</title>
  26. <author id="4">李刚</author>
  27. </book>
  28. </books>
  29. </value>
  30. </response>
  31. '''
  32.  
  33. //开始解析此xml数据
  34. def xmlSluper = new XmlSlurper()
  35. def response = xmlSluper.parseText(xml)
  36. //println response.value.books[0].book[0].title.text()
  37. //println response.value.books[0].book[0].author.text()
  38. //println response.value.books[1].book[0].@available
  39. def list = []
  40. response.value.books.each { books ->
  41. //下面开始对书结点进行遍历
  42. books.book.each { book ->
  43. def author = book.author.text()
  44. if (author.equals('李刚')) {
  45. list.add(book.title.text())
  46. }
  47. }
  48. }
  49. //println list.toListString()
  50. //深度遍历xml数据
  51. def titles = response.depthFirst().findAll { book ->
  52. return book.author.text() == '李刚' ? true : false
  53. }
  54. //println titles.toListString()
  55. //广度遍历xml数据
  56. def name = response.value.books.children().findAll { node ->
  57. node.name() == 'book' && node.@id == '2'
  58. }.collect { node ->
  59. return node.title.text()
  60. }
  61. //println name

 

普通文件的读写

java文件处理

  1. 节点流:InputStream,OutputStream及其子类
  2. 处理流:ReaderWriter及其子类

所有java对文件的处理类,groovy都可以使用

groovy扩展了许多更加快捷和强大的方法

代码示范:

  1. def file = new File(pathname:'../../test.txt')
  2. file.eachline { line ->
  3. println line
  4. }
  5. def text = file.getText()
  6. println text
  7. def result = file.readLines()
  8. //读取文件部分内容
  9. def reader = file.withReader { reader ->
  10. char[] buffer = new char[100]
  11. reader.read(buffer)
  12. return buffer
  13. }
  14. println reader
  15. def copy(String sourcePath, String destationPath) {
  16. try {
  17. //首先创建目标文件
  18. def desFile = new File(destationPath)
  19. if (!desFile.exists()) {
  20. desFile.createNewFile()
  21. }
  22. //开始copy
  23. new File(sourcePath).withReader { reader ->
  24. def lines = reader.readLines()
  25. desFile.withWriter { writer ->
  26. lines.each { line ->
  27. writer.append(line + "\r\n")
  28. }
  29. }
  30. }
  31. return true
  32. } catch (Exception e) {
  33. e.printStackTrace()
  34. }
  35. return false
  36. } 

groovy与java对比

  • 没有java那么多的限制
  • 对java的功能进行了极大的扩展
  • 既可以编写应用,也可以编写脚本

语法上区别:

  • Groovy 语句可以不用分号结尾
  • 定义变量的时候可以不指定其类型、Groovy 中函数的返回值也可以是无类型的
  • 最后一行代码的执行结果就是函数的返回值
  • 如果指定了函数返回类型,则可不必加 def 关键字来定义函数
  • Groovy中函数调用的时候还可以不加括号
  • 闭包是一段代码,所以需要用花括号括起来
  • -> 箭头前面是参数定义,箭头后面是代码
  • Groovy 中,当函数的最后一个参数是闭包的话,可以省略圆括号或闭包放在后面
  • 如果发送的实参的个数多于方法的形参个数,而且多出的实参是名值对,那么Groovy会假设方法的第一个形参是一个Map,然后将实参列表中的所有名值对组织到一起,作为第一个形参的值,之后,再将剩下的实参按照给出的顺序赋给其他的形参,就和我们输出的结果一样。

原文链接:http://www.cnblogs.com/yufecheng/p/11302777.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号