Groovy学习笔记

邓平凡Gradle教程的搬运工

Groovy的文件形式

  1. test.groovy 文件以groovy后缀
  2. 每个文件对应一个对象
  3. 两种写法:class,脚本

形式一

文件名:Person.groovy

package bean
class Person {
    String name
    String gender
    Person(name, gender) {
        this.name = name
        this.gender = gender
    }
    def print() {
        println name + " " + gender
    }
}

形式二:脚本

特点:直接可以运行(java需要在main()函数中执行)
文件名:run.groovy
功能:引用并创建了Person对象,调用他的方法

import bean.Person
def name = 'EvilsoulM'
def person=new Person(name,"male");
person.print()

脚本是啥

Groovy文件都会编译成class文件运行在jvm上
猜想:脚本会不会编译成java类然后把代码都放到main函数中,
类似jsp脚本都会编译成类servlet然后运行在service方法中

就是这样的

Groovy把它转换成这样的Java类:

groovyc -d classes test.groovy

groovyc是groovy
的编译命令,-d classes用于将编译得到的class文件拷贝到classes文件夹下

jd-gui反编译它的代码:

Groovy学习笔记_第1张图片

  • test.groovy被转换成了一个test类,它从script派生。
  • 每一个脚本都会生成一个static main函数。这样,当我们groovy test.groovy的时候,其实就是用java去执行这个main函数
  • 脚本中的所有代码都会放到run函数中。比如,println ‘Groovy world’,这句代码实际上是包含在run函数里的。
  • 如果脚本中定义了函数,则函数会被定义在test类中。

定义成员变量

在脚本中定义成员变量

import groovy.transform.Field;   //必须要先import
@Field x = 1  <==在x前面加上@Field标注,这样,x就彻彻底底是test的成员变量了。

文件名:ScriptBase.groovy

import groovy.transform.Field;
@Field author = 'EvilsouM'
@Field gender = 'male'
@Field age = 25
//必须要先import
def printInfo() {
    println "name->$author  gender->$gender age->$age"
}

在class中定义成员变量

文件名:ScriptBase.groovy

class ScriptBase {
    def author = 'EvilsouM'
    def gender = 'male'
    def age = 25
    def printInfo() {
        println "name->$author  gender->$gender age->$age"
    }
}

调用ScriptBase类:

def Closure printAuthorInfo = {
            String name, String gender, int age ->
                println "name->$name  gender->$gender age->$age"
}
def ScriptBase base = new ScriptBase()
base.printInfo()
printAuthorInfo.call(base.author, base.gender, base.age) 上面两种方式都能拿到成员变量

一个细节

所有表达式或者声明都不用加分号结尾

一个中心(变量)

def var =1 
def str= "i am a person"
def int x = 1//也可以指定类型

两个基本点(函数和过程)

函数声明

def  nonReturnTypeFunc(){
     last_line   //最后一行代码的执行结果就是本函数的返回值
}
//如果指定了函数返回类型,则可不必加def关键字来定义函数
String  getString(){
   return "I am a string"
}
  1. 使用def声明函数时的参数 无返回类型,无return
  2. 不使用def声明时,需要指明返回类型和return
  3. 不需要定义参数类型,JavaScript中也一样

函数调用

函数调用可以不加括号,这和属性的引用容易混淆

函数名称+( )/(参数值)
函数名称 参数值

字符串搞法

三种写法:
- ‘string’
- “string”
- ”’string”’

区别:
Groovy对字符串支持相当强大,充分吸收了一些脚本语言的优点:
1 单引号”中的内容严格对应Java中的String,不对$符号进行转义

def singleQuote='I am $ dolloar'  //输出就是I am $ dolloar

2 双引号”“的内容则和脚本语言的处理有点像,如果字符中有 表达式先求值。

def doubleQuoteWithoutDollar = "I am one dollar" //输出 I am one dollar
def x = 1
def doubleQuoteWithDollar = "I am $x dolloar" //输出I am 1 dolloar

3 三个引号”’xxx”’中的字符串支持随意换行 比如

def multieLines = ''' begin
   line  1 
   line  2
   end '''

数据类型

  • 一个是Java中的基本数据类型。
  • 另外一个是Groovy中的容器类。
  • 最后一个非常重要的是闭包。

基本数据类型

作为动态语言,Groovy世界中的所有事物都是对象。所以,int,boolean这些Java中的基本数据类型,在Groovy代码中其实对应的是它们的包装数据类型。比如int对应为Integer,boolean对应为Boolean

容器类

基本用法参考:http://www.groovy-lang.org/api.html

list

变量定义:List变量由[]定义,比如

def aList = [5,'string',true] //List由[]定义,其元素可以是任何对象

变量存取:可以直接通过索引存取,而且不用担心索引越界。如果索引超过当前链表长度,List会自动
往该索引添加元素

assert aList[1] == 'string'
assert aList[5] == null //第6个元素为空
aList[100] = 100  //设置第101个元素的值为10
assert aList[100] == 100

那么,aList到现在为止有多少个元素呢?

println aList.size  ===>结果是101

map

变量定义:Map变量由[:]定义,比如

def aMap = ['key1':'value1','key2':true] 

Map由[:]定义,注意其中的冒号。冒号左边是key,右边是Value。key必须是字符串,value可以是任何对象。另外,key可以用''""包起来,也可以不用引号包起来。比如

def aNewMap = [key1:"value",key2:true] //其中的key1和key2默认被
处理成字符串"key1""key2"

不过Key要是不使用引号包起来的话,也会带来一定混淆,比如

def key1="wowo"
def aConfusedMap=[key1:"who am i?"]

aConfuseMap中的key1到底是"key1"还是变量key1的值“wowo”?显然,答案是字符串"key1"。如果要是"wowo"的话,则aConfusedMap的定义必须设置成:

def aConfusedMap=[(key1):"who am i?"]

Map中元素的存取更加方便,它支持多种方法:

println aMap.keyName    <==这种表达方法好像key就是aMap的一个成员变量一样
println aMap['keyName'] <==这种表达方法更传统一点
aMap.anotherkey = "i am map"  <==为map添加新元素

range

def aRange = 1..5  <==Range类型的变量 由begin值+两个点+end值表示
                      左边这个aRange包含1,2,3,4,55个值

如果不想包含最后一个元素,则

def aRangeWithoutEnd = 1..<5  <==包含1,2,3,44个元素
println aRange.from
println aRange.to

闭包

JavaScript中闭包是一个函数
Groovy中闭包是一种数据类型:Closure

定义形式

def xxx = {paramters -> code}  //或者  
def xxx = {无参数,纯code}  这种case不需要->符号
def aClosure = {//闭包是一段代码,所以需要用花括号括起来..  
    String param1, int param2 ->  //这个箭头很关键。箭头前面是参数定义,箭头后面是代码  
    println"this is code" //这是代码,最后一句是返回值,  
   //也可以使用return,和Groovy中普通函数一样  
}

和定义函数的区别:

  1. 花括号
  2. 参数需要定义类型,没有返回值类型
  3. 有返回值:最后一行执行结果或者return

闭包的使用

和函数调用差不多
可以是用call方法

Closure.call("this is string",100)
aClosure("this is string", 100)

闭包作为函数参数

def iamList = [1,2,3,4,5]  //定义一个List
iamList.each{  //调用它的each,这段代码的格式看不懂了吧?each是个函数,圆括号去哪了?
      println it//默认参数为it
}

文件操作

参考API:http://docs.groovy-lang.org/latest/html/groovy-jdk/java/io/File.html

读文件

1 读该文件中的每一行:eachLine的唯一参数是一个Closure。Closure的参数是文件每一行的内容
其内部实现肯定是Groovy打开这个文件,然后读取文件的一行,然后调用Closure…

def File targetFile = new File("build.gradle")
targetFile.eachLine {
    String line ->
        println line
}

2 直接得到文件内容

targetFile.getBytes()  <==文件内容一次性读出,返回类型为byte[]

3 使用InputStream.InputStream的SDK在 http://docs.groovy-lang.org/latest/html/groovy-jdk/java/io/InputStream.html

def ism =  targetFile.newInputStream()  
//操作ism,最后记得关掉  
ism.close

4 使用闭包操作inputStream,以后在Gradle里会常看到这种搞法

 targetFile.withInputStream{
 ism -> 操作ism. 不用close。Groovy会自动替你close
}

写文件

和读文件差不多。不再啰嗦。这里给个例子,告诉大家如何copy文件。

def srcFile = new File(源文件名)
def targetFile = new File(目标文件名)
targetFile.withOutputStream{
os-> srcFile.withInputStream {
ins->
   os << ins //利用OutputStream的<<操作符重载,完成从inputstream到OutputStream  //的输出
  }
}

你可能感兴趣的:(其他语言学习)