Groovy入门

Groovy概述
Groovy是Apache 旗下的一种基于JVM的面向对象编程语言,既可以用于面向对象编程,也可以用作纯粹的脚本语言。在语言的设计上它吸纳了Python、Ruby 和 Smalltalk 语言的优秀特性,比如动态类型转换、闭包和元编程支持。
Groovy与 Java可以很好的互相调用并结合编程 ,比如在写 Groovy 的时候忘记了语法可以直接按Java的语法继续写,也可以在 Java 中调用 Groovy 脚本。比起Java,Groovy语法更加的灵活和简洁,可以用更少的代码来实现Java实现的同样功能。

1.变量
Groovy中用def关键字来定义变量,可以不指定变量的类型,默认访问修饰符是public。

task variable <<{
   def a=10
   def float b=10.5f
   def c="Haha"
   println(a)
   println(b)
   println(c)
}

2.方法
方法使用返回类型或def关键字定义,方法可以接收任意数量的参数,这些参数可以不申明类型,如果不提供可见性修饰符,则该方法为public。

(1)用def关键字来定义方法

task method << {
    def result1=add(2,4)
    def result2=sub(4,2)
    println "result1:"+result1+",result2:"+result2
    printStr()
}

def add(int a,int b)
{
    return a+b
}

def sub(a,b)
{
    return a-b
}

def printStr()
{
    println "Print Something"
}

(2)如果指定了方法返回类型,可以不需要def关键字来定义方法。

task method << {
    def result1=add(2,4)
    def result2=sub 4,2
    println "result1:"+result1+",result2:"+result2
    
}

int add(int a,int b)
{
    return a+b
}

int sub(a,b)
{
    return a-b
}

(3)如果不使用return ,方法的返回值为最后一行代码的执行结果。

task method << {
    def result1=add(2,4)
    def result2=sub 4,2
    println "result1:"+result1+",result2:"+result2
    
}

int add(int a,int b)
{
    a+b
}

int sub(a,b)
{
     a-b
}

从上面的几段代码可以看出,Groovy代码可以省略的地方有如下几处:
1.语句后面的分号可以省略。
2.方法的括号可以省略,比如注释1和注释3处。
3.参数类型可以省略,比如注释2处。
4.return可以省略掉,比如注释4处。

3.类
Groovy类非常类似于Java类。

task testClass << {

   def p=new Person()
   p.increaseAge 10
   println "Age:"+p.age


}

class Person{
   String name
   Integer age=10

   def increaseAge(Integer years)
   {
       this.age+=years
   }

}

Groovy类与Java类有以下的区别:
默认类的修饰符为public。
没有可见性修饰符的字段会自动生成对应的setter和getter方法。
类不需要与它的源文件有相同的名称,但还是建议采用相同的名称。

4.语句
(1)断言
Groovy断言和Java断言不同,它一直处于开启状态,是进行单元测试的首选方式。

task testAssert << {
     assert 1+2==6
}

运行结果:


image.png

当断言的条件为false时,程序会抛出异常,不再执行下面的代码,从输出可以很清晰的看到发生错误的地方。

(2)for循环
Groovy支持Java的for(int i=0;i<N;i++)和for(int i :array)形式的循环语句,另外还支持for in loop形式,支持遍历范围、列表、Map、数组和字符串等多种类型。

task testFor <<  {

   //遍历范围
   def x=0
   for(i in 0..3)
   {
       x+=i
    }

    assert x==6

    //遍历列表
    x=0
    for(i in [0,1,2,3])
    {
        x+=i
     }

     assert x==6

    //遍历Map中的值
    def map=['a':1,'b':2,'c':3]
    x=0
    for(v in map.values())
    {
         x+=v
    }
    
    assert x==6

}

(3)Switch语句
Groovy中的Switch语句不仅兼容Java代码,还可以处理更多类型的case表达式。

task testSwitch <<  {

    def x=16
    def result=""
    switch(x)
    {
       case "ok":
            result="found ok"
            break
       case [1,2,3,'List']:
            result="list"
            break
       case 10..19:
            result="range"
            break
       case Integer:
            result="integer"
            break
       default:
            result="default"
            break
    }
   

   assert result=="integer"
}

case表达式可以是字符串、列表、范围、Integer等等,因为篇幅原因,这里只列出了一小部分。

5.数据类型

Groovy中的数据类型主要有以下几种:

Java中的基本数据类型
Groovy中的容器类
闭包

(1) 字符串

Groovy中的基本数据类型和Java大同小异,这里主要介绍下字符串类型。在Groovy种有两种字符串类型,普通字符串String(java.lang.String)和插值字符串GString(groovy.lang.GString)。

单引号字符串
在Groovy中单引号字符串和双引号字符串都可以定义一个字符串常量,只不过单引号字符串不支持插值。

'Android进阶解密'
双引号字符串
要想插值可以使用双引号字符串,插值指的是替换字符串中的占位符,占位符表达式为{}或者以为前缀。

def name = 'Android进阶之光'
println "hello ${name}"
println "hello $name"

三引号字符串
三引号字符串可以保留文本的换行和缩进格式,不支持插值.

task method <<{
def name = '''Android进阶之光
       Android进阶解密
Android进阶?'''
println name 
}

打印结果为:

Android进阶之光
       Android进阶解密
Android进阶?

GString
String是不可变的,GString却是可变的,GString和String即使有相同的字面量,它们的hashCodes的值也可能不同,因此应该避免使用使用GString作为Map的key。

assert "one: ${1}".hashCode() != "one: 1".hashCode()

当双引号字符串中包含插值表达式时,字符串类型为GString,因此上面的断言为true。

(2)List
Groovy没有定义自己的集合类,它在Java集合类的基础上进行了增强和简化。Groovy的List对应Java中的List接口,默认的实现类为Java中的ArrayList。

def number = [1, 2, 3]         
assert number instanceof List  
def linkedList = [1, 2, 3] as LinkedList    
assert linkedList instanceof java.util.LinkedList

可以使用as操作符来显式指定List的实现类为java.util.LinkedList。
获取元素同样要比Java要简洁些,使用[]来获取List中具有正索引或负索引的元素。

task method <<{
def number  = [1, 2, 3, 4]   
assert number [1] == 2
assert number [-1] == 4 //1  

number << 5     //2             
assert number [4] == 5
assert number [-1] == 5
}

注释1处的索引-1是列表末尾的第一个元素。注释2处使用<<运算符在列表末尾追加一个元素。

(3) Map

创建Map同样使用[],需要同时指定键和值,默认的实现类为java.util.LinkedHashMap。

def name = [one: '魏无羡', two: '杨影枫', three: '张无忌']   
assert name['one']  == '魏无羡' 
assert name.two  == '杨影枫'

Map还有一个键关联的问题:

def key = 'name'
def person = [key: '魏无羡'] //1
assert person.containsKey('key') 
person = [(key): '魏无羡'] //2       
assert person.containsKey('name') 

注释1处魏无羡的键值是key这个字符串,而不是key变量的值 name。如果想要以key变量的值为键值,需要像注释2处一样使用(key),用来告诉解析器我们传递的是一个变量,而不是定义一个字符串键值。

(4)闭包
Groovy中的闭包是一个开放的、匿名的、可以接受参数和返回值的代码块。
定义闭包
闭包的定义遵循以下语法:

{ [closureParameters -> ] statements }

闭包分为两个部分,分别是参数列表部分[closureParameters -> ]和语句部分 statements 。
参数列表部分是可选的,如果闭包只有一个参数,参数名是可选的,Groovy会隐式指定it作为参数名,如下所示。

{ println it }     //使用隐式参数it的闭包      

当需要指定参数列表时,需要->将参数列表和闭包体相分离。

{ it -> println it }   //it是一个显示参数 
{ String a, String b ->                                
    println "${a} is a ${b}"
}   

闭包是groovy.lang.Cloush类的一个实例,这使得闭包可以赋值给变量或字段,如下所示。

//将闭包赋值给一个变量
def println ={ it -> println it }     
assert println instanceof Closure
//将闭包赋值给Closure类型变量
Closure do= { println 'do!' }            

调用闭包
闭包既可以当做方法来调用,也可以显示调用call方法。

def code = { 123 }
assert code() == 123 //闭包当做方法调用
assert code.call() == 123 //显示调用call方法
def isOddNumber = { int i -> i%2 != 0 }                           
assert isOddNumber(3) == true  //调用带参数的闭包

6.I/O操作
Groovy的 I/O 操作要比Java的更为的简洁。

(1)文件读取
可以先建立一个txt文件,在其中输入一些内容,然后用来读取。

task testReadFile <<  {

    def filePath="E:/test.txt"
    def file=new File(filePath)
    file.eachLine{
         println it
    }

}

可以看出Groovy的文件读取是很简洁的,还可以更简洁些:

def filePath = "D:/Android/name.txt"
def file = new File(filePath) ;
println file.text

(2)文件写入
文件写入也是比较简洁的。

task testWriteFile  <<  {
    def fileName="E:/test.txt"
    def file=new File(fileName)
    file.withPrintWriter{
       it.println("Kobe")
       it.println("James")
    }

}

7.其他

(1)asType
asType用于类型转换。

task testAsType << {
     String a='23'
     int b=a as int
     def c=a.asType(Integer)
     assert c instanceof java.lang.Integer    
}

(2)判断是否为真

if (name != null && name.length > 0) {}

替换为

if (name) {}

(3)安全取值
在Java中,要安全获取某个对象的值可能需要大量的if语句来判空:

if (school != null) {
    if (school.getStudent() != null) {
        if (school.getStudent().getName() != null) {
            System.out.println(school.getStudent().getName());
        }
    }
}

Groovy中可以使用?.来安全的取值:

println school?.student?.name

(4)with操作符
对同一个对象的属性进行赋值时,可以这么做:

task method <<{
Person p = new Person()
p.name = "杨影枫"
p.age = 19
p.sex = "男"
println p.name
}
class Person {                       
    String name                      
    Integer age
    String sex
}

使用with来进行简化:

Person p = new Person()
p.with {
   name = "杨影枫"
   age= 19
   sex= "男"
 }   
println p.name
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容

  • 变量定义 groovy 是动态类型的语言,也就是说不需要指定变量的类型,类型是可以值来推导的。 不指定类型定义变量...
    zachaxy阅读 776评论 0 0
  • 环境安装: JDK环境,如果用AndroidStudio的话可以跳过该步骤,因为AndroidStudio的JDK...
    MinicupSimon阅读 1,053评论 2 1
  • 前言 由于项目需要用到 Groovy 语言,这两天对其进行了粗略的学习,本文是对学习做的一个简单总结,主要内容参考...
    简单的土豆阅读 188,540评论 12 201
  • 在海边,也是大陆的边缘我们在临近时间幻灭的一刻放出彼此的微笑,摊开手掌季节的敕令中,准备再次沉默 留给爱情的肉体,...
    印虹阅读 282评论 0 2
  • 生活中因“玻璃心”倒下的人不在少数,是什么造成的“玻璃心”?自尊与自卑是同一事物的一体两面,它们是个人内心自我价值...
    锦虹心理阅读 879评论 0 0