Groovy入门

图片发自简书App

环境安装:

JDK环境,如果用AndroidStudio的话可以跳过该步骤,因为AndroidStudio的JDK 及 Groovy已默认配置好
官网下载:http://www.groovy-lang.org/download.html
可以直接下载压缩包,解压,手动配置环境变量
或(推荐)直接下载Windows Installer并安装,环境变量自动配好。
打开cmd -> groovy -version 验证

或者用在线运行环境 :
https://tool.lu/coderunner/
http://www.dooccn.com/groovy/

Groovy HelloWorld:

1.命令行

创建helloworld.groovy文件:

class Fuck{
    static void main(String[] args){
        println "Hello World3";
    }
}

Shift 鼠标右键-> 在此处打开命令窗口
运行命令 groovy helloworld.groovy

2.Groovy安装后在%GROOVY_HOME%/bin下找到groovyConsole.exe或groovyConsole.bat.
image.png

Ctrl Enter / Ctrl R 运行。
同时支持选中部分运行

3使用AndroidStudio:

Ctrl+Shift+A->选择Groovy Console即可


image.png

或双击Shift->选择Groovy Console


image.png

出现两个窗口:Groovy脚本输入窗口,和Run脚本输出窗口

Ctrl Enter / Ctrl R 运行。
同时支持选中部分运行

对比Java

  1. Default imports
    java.io.*
    java.lang.*
    java.math.BigDecimal
    java.math.BigInteger
    java.net.*
    java.util.*
    groovy.lang.*
    groovy.util.*

  2. Multi-methods 或者叫Runtime Dispatch
    java基于方法声明的类型,在编译期间就确定了调用的方法,而Groovy则是在运行时来判断参数的类型,而动态的调用相应的方法。

int method(String arg) {
    return 1;
}
int method(Object arg) {
    return 2;
}
Object o = "Object";
int result = method(o);

Java运行后 result为2;
而Groovy运行后 result 为1;
  1. Array initializers
    Groovy 中的{...}被保留用作闭包,数组初始化使用[]。
    Java: int[] array = {1, 2, 3}
    Groovy: int[] array = [1, 2, 3]

  2. Package scope visibility

class Person {
    String name
}

Java中,成员变量不定义访问控制符的情况下为default, 包相同的类中可以访问。即package-private

Groovy中,不定义访问控制符的成员变量被用于创建一个属性,即一个私有成员变量,一个关联的getter和一个关联的setter。如果希望达到Java包私有的效果,只需要加注释@PackageScope

class Person {
    @PackageScope String name
}
  1. 不支持ARM blocks (Automatic Resource Management)
Path file = Paths.get("/path/to/file");
Charset charset = Charset.forName("UTF-8");
try (BufferedReader reader = Files.newBufferedReader(file, charset)) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }

} catch (IOException e) {
    e.printStackTrace();
}

可以写成:
new File('/path/to/file').eachLine('UTF-8') {
   println it
}
或更接近于Java写法的:
new File('/path/to/file').withReader('UTF-8') { reader ->
   reader.eachLine {
       println it
   }
}
  1. Lambdas
    Java8支持的Lambdas
Runnable run = () -> System.out.println("Run");
list.forEach(System.out::println);

Groovy不支持,但是通过闭包实现相同效果。

Runnable run = { println 'run' }
list.each { println it } // or list.each(this.&println)

Extra keywords
Groovy比Java多出以下几个关键字:as, def, in, trait

Grammar

Groovy是基于JVM的开发语言,与Java有很多相似之处。以下只介绍与Java不同的语法:

范围运算符

class Example { 
   static void main(String[] args) { 
      //1..10 - 包含范围的示例
      //1 .. <10 - 独占范围的示例
      //'a'..'x' - 范围也可以由字符组成
      //10..1 - 范围也可以按降序排列
      //'x'..'a' - 范围也可以由字符组成并按降序排列。

      def range = 5..10; 
      println(range); 
      println(range.get(2)); 
   } 
}

[5, 6, 7, 8, 9, 10] 
7

方法

//返回类型用具体的或使用def关键字定义, 方法可以接收任意数量的参数
//定义参数时,不必显式定义类型
//修饰符public,private和protected。不写默认为public
def methodName() { 
   //Method code 
}

static def DisplayName(parameter1, parameter2 = 0, parameter3 = 0) {
  //参数设置默认值,调用DisplayName(1)时,会默认使用 parameter2,parameter3的默认值。
} 
    
static void main(String[] args) {
} 

文件操作

import java.io.File 
class Example { 
   static void main(String[] args) { 
      //读取文件
      new File("E:/Example.txt").eachLine {  
         line -> println "line : $line"; 
      } 
      //读取文件的内容
      File file = new File("E:/Example.txt") 
      println file.text 

      //写入文件
      new File('E:/','Example.txt').withWriter('utf-8') { 
         writer -> writer.writeLine 'Hello World' 
      }  

      //获取文件的大小
      File file = new File("E:/Example.txt")
      println "The file ${file.absolutePath} has ${file.length()} bytes"

      //测试文件是否是目录
      def file = new File('E:/') 
      println "File? ${file.isFile()}" 
      println "Directory? ${file.isDirectory()}" 

      //创建目录 删除文件
      def file = new File('E:/Directory')
      file.mkdir()
      file.delete()
      //复制文件
      def src = new File("E:/Example.txt")
      def dst = new File("E:/Example1.txt")
      dst << src.text

      //显示机器上的驱动器
      def rootFiles = new File("test").listRoots() 
      rootFiles.each { 
         file -> println file.absolutePath 
      }

      //列出特定目录中的文件
      new File("E:/Temp").eachFile() {  
         file->println file.getAbsolutePath()
      }

      //显示目录及其子目录中的所有文件
      new File("E:/temp").eachFileRecurse() {
         file -> println file.getAbsolutePath()
      }
   } 
}

数字

rint(): 返回值最接近参数的整数

class Example { 
   static void main(String[] args){ 
      double d = 100.675; 
      double e = 100.500; 
      double f = 100.200;
        
      System.out.println(Math.rint(d)); 
      System.out.println(Math.rint(e)); 
      System.out.println(Math.rint(f)); 
   } 
}

101.0 
100.0 
100.0

toRadians():参数值转换为弧度

class Example {
   static void main(String[] args) {
      double x = 45.0;
      double y = 30.0;  
        
      System.out.println( Math.toRadians(x) );
      System.out.println( Math.toRadians(y) );
   } 
}

0.7853981633974483 
0.5235987755982988 

字符串

class Example { 
   static void main(String[] args) { 
      String a = 'Hello Single'; 
      String b = "Hello Double"; 
      String c = "'Hello Triple" + "Multiple lines'";
      println(a); 
      println(b); 
      println(c); 
      //字符串索引
      println(sample[4]); // Print the 5 character in the string
      println(sample[-1]);  //Print the 1st character in the string starting from the back 
      println(sample[1..2]);//Prints a string starting from Index 1 to 2 
      println(sample[4..2]);//Prints a string starting from Index 4 back to 2 
      //字符串重复
      String a = "Hello"; 
      println("Hello"*3); 
      println(a*3); 
   } 
}
Hello Single 
Hello Double 
'Hello TripleMultiple lines'

o 
d 
el 
oll 

HelloHelloHello 
HelloHelloHello

列表
[11,12,13,14] - 整数值列表
['Angular','Groovy','Java'] - 字符串列表
[1,2,[3,4],5] - 嵌套列表
['Groovy',21,2.11] - 异构的对象引用列表
[] - 一个空列表

class Example {
   static void main(String[] args) {
      def lst = [11, 12, 13, 14];
      println(lst);
      lst.add(15);//将新值附加到此列表的末尾。
      println(lst);
      lst.add(2,20);//将新值附加到列表中的特定位置。
      println(lst);

      println(lst.contains(12)); //true
      println(lst.contains(18));//false

      println(lst.get(0));//11
      println(lst.get(2));//13

      println(lst.isEmpty()); //false 

      //从列表中减去的值的集合。
      def newlst = [];
      newlst = lst.minus([12,13]); 
      println(newlst); //[11, 14]
      newlst = lst.plus([15,16]);
      println(newlst);  //[11, 14, 15, 16]

      //从此列表中删除最后一个项目。
      println(lst.pop()); //14 
      println(lst); //[11, 12, 13]

      //删除此列表中指定位置的元素。
      println(lst.remove(2));//13
      println(lst);//[11, 12]

      //创建与原始列表的元素相反的新列表
      def revlst = lst.reverse(); 
      println(revlst); //[12, 11]

       //排序
      def newlst = lst.sort(); 
      println(newlst);//[11, 12]

      println(lst.size);//2
   } 
}

[11, 12, 13, 14] 
[11, 12, 13, 14, 15] 
[11, 12, 20, 13, 14, 15]

正则

有两个特殊的位置字符用于表示一行的开始和结束:caret(∧)和美元符号($)。
正则表达式也可以包括量词。加号(+)表示一次或多次,应用于表达式的前一个元素。
星号(*)用于表示零个或多个出现。问号(?)表示零或一次。
元字符{和}用于匹配前一个字符的特定数量的实例。
在正则表达式中,句点符号(。)可以表示任何字符。这被描述为通配符。
正则表达式可以包括字符类。一组字符可以作为简单的字符序列,包含在元字符[和]中,如[aeiou]中。对于字母或数字范围,可以使用[a-z]或[a-mA-M]中的短划线分隔符。字符类的补码由方括号内的前导插入符号表示,如[∧a-z]中所示,并表示除指定的字符以外的所有字符。下面给出了正则表达式的一些示例。

以下都为true
'Groovy' =~ 'Groovy' //true
'Groovy' =~ 'oo' //true
'Groovy' ==~ 'Groovy' //true
'Groovy' ==~ 'oo' //false
'Groovy' =~ '∧G' //true
‘Groovy' =~ 'y$' //true
‘Groovy' =~ 'Gro*vy' //true
'Groovy' =~ 'Gro{2}vy'//true

特征

可以被看作是承载默认实现和状态的接口。使用trait关键字定义

class Example {
   static void main(String[] args) {
      Student st = new Student();
      st.StudentID = 1;
      st.Marks1 = 10;   
      println(st.DisplayMarks());
      println(st.DisplayTotal());
   } 
} 
interface Total {
   void DisplayTotal() 
} 
trait Marks implements Total { //实现接口
   void DisplayMarks() {
      println("Display Marks");
   }
   void DisplayTotal() {
      println("Display Total"); 
   } 
} 
class Student implements Marks { 
   int StudentID
   int Marks1;  
} 
Display Marks 
Display Total

闭包

class Example {
   static void main(String[] args) {
      def clos = {println "Hello World"}; //{println "Hello World"}即为闭包
      clos.call();//代码块可以使用call语句执行
   } 
}
class Example {
   static void main(String[] args) {
      def clos = {param->println "Hello ${param}"};//包含形式参数
      clos.call("World");
   } 
}
class Example {
   static void main(String[] args) {
      def clos = {println "Hello ${it}"};//这里的'it'是Groovy中的关键字
      clos.call("World"); //Hello World
   } 
}


class Example { 
   def static Display(clo) {
      clo.call("Inner");
   } 
   static void main(String[] args) {
      def str1 = "Hello";
      def clos = { param -> println "${str1} ${param}" }//闭包内引用变量
      clos.call("World");//Hello World
        
      str1 = "Welcome";
      clos.call("World");// Welcome World
        
      Example.Display(clos);// Welcome Inner
   } 
}

class Example {
   static void main(String[] args) {
      def lst = [11, 12, 13, 14];
      lst.each {println it}//each接收一个Closure参数, 应用在数组的每一项.
      lst.each{num -> if(num % 2 == 0) println num} // 12 14
   } 
}

class Example {
   static void main(String[] args) {
      def mp = ["TopicName" : "Maps", "TopicDescription" : "Methods in Maps"]             
      mp.each {println it}
      //TopicName = Maps 
      //TopicDescription = Methods in Maps 

      mp.each {println "${it.key} maps to: ${it.value}"}
      //TopicName maps to: Maps 
      //TopicDescription maps to: Methods in Maps
   } 
}

class Example {
   static void main(String[] args) {
      def lst = [1,2,3,4];
      def value;
      value = lst.find {element -> element > 2} // 查找集合中与某个条件匹配的第一个值
      println(value);//3

      value = lst.findAll{element -> element > 2}//找到接收对象中与闭合条件匹配的所有值。
      value.each {println it}//3, 4

      // Is there any value above 2
      value = lst.any{element -> element > 2}
      println(value);//true
        
      // Is there any value above 4
      value = lst.any{element -> element > 4}
      println(value); //false

      // Are all value above 2
      value = lst.every{element -> element > 2}
      println(value);//false
        
      // Are all value above 4 
      value = lst.every{element -> element > 4}
      println(value);  //false

      def largelst = [4,5,6];
        
      // Are all value above 2
      value = largelst.every{element -> element > 2}
      println(value);//true

      def lst = [1,2,3,4];
      def newlst = [];
      newlst = lst.collect {element -> return element * element}//通过集合收集迭代,使用闭包作为变换器将每个元素转换为新值。
      println(newlst);//[1, 4, 9, 16] 
   } 
}

XML

Groovy中的XML支持
Groovy语言还提供了对XML语言的丰富支持。使用的两个最基本的XML类是 -

XML标记构建器 - Groovy支持基于树的标记生成器BuilderSupport,它可以被子类化以生成各种树结构对象表示。通常,这些构建器用于表示XML标记,HTML标记。 Groovy的标记生成器捕获对伪方法的调用,并将它们转换为树结构的元素或节点。这些伪方法的参数被视为节点的属性。作为方法调用一部分的闭包被视为生成的树节点的嵌套子内容。

import groovy.xml.MarkupBuilder 

class Example {
   static void main(String[] args) {
      def mB = new MarkupBuilder()
        
      // Compose the builder
      mB.collection(shelf : 'New Arrivals') {
         movie(title : 'Enemy Behind')
         type('War, Thriller')
         format('DVD')
         year('2003')
         rating('PG')
         stars(10)
         description('Talk about a US-Japan war') 
      }
   } 
}
<collection shelf = 'New Arrivals'> 
   <movie title = 'Enemy Behind' /> 
      <type>War, Thriller</type> 
      <format>DVD</format> 
      <year>2003</year> 
      <rating>PG</rating> 
      <stars>10</stars> 
      <description>Talk about a US-Japan war</description> 
   </movie> 
</collection>

XML解析器 - Groovy XmlParser类使用一个简单的模型来将XML文档解析为Node实例的树。每个节点都有XML元素的名称,元素的属性和对任何子节点的引用。这个模型足够用于大多数简单的XML处理。

class Example {

   static void main(String[] args) { 
    
      def parser = new XmlParser()
      def doc = parser.parse("D:Movies.xml");
        
      doc.movie.each{
         bk->
         print("Movie Name:")
         println "${bk['@title']}"
            
         print("Movie Type:")
         println "${bk.type[0].text()}"
            
         print("Movie Format:")
         println "${bk.format[0].text()}"
            
         print("Movie year:")
         println "${bk.year[0].text()}"
            
         print("Movie rating:")
         println "${bk.rating[0].text()}"
            
         print("Movie stars:")
         println "${bk.stars[0].text()}"
            
         print("Movie description:")
         println "${bk.description[0].text()}"
         println("*******************************")
      }
   }
} 

监视JVM

import java.lang.management.*

def os = ManagementFactory.operatingSystemMXBean 
println """OPERATING SYSTEM: 
    OS architecture = $os.arch 
    OS name = $os.name 
    OS version = $os.version 
    OS processors = $os.availableProcessors 
""" 
 
def rt = ManagementFactory.runtimeMXBean 
println """RUNTIME: 
    Runtime name = $rt.name 
    Runtime spec name = $rt.specName 
    Runtime vendor = $rt.specVendor 
    Runtime spec version = $rt.specVersion 
    Runtime management spec version = $rt.managementSpecVersion 
   """ 

def mem = ManagementFactory.memoryMXBean 
def heapUsage = mem.heapMemoryUsage 
def nonHeapUsage = mem.nonHeapMemoryUsage 

println """MEMORY: 
   HEAP STORAGE: 
        Memory committed = $heapUsage.committed 
        Memory init = $heapUsage.init 
        Memory max = $heapUsage.max 
        Memory used = $heapUsage.used NON-HEAP STORAGE: 
        Non-heap memory committed = $nonHeapUsage.committed 
        Non-heap memory init = $nonHeapUsage.init 
        Non-heap memory max = $nonHeapUsage.max 
        Non-heap memory used = $nonHeapUsage.used 
   """
  
println "GARBAGE COLLECTION:" 
ManagementFactory.garbageCollectorMXBeans.each { gc ->
   println "    name = $gc.name"
   println "        collection count = $gc.collectionCount"
   println "        collection time = $gc.collectionTime"
   String[] mpoolNames =   gc.memoryPoolNames
    
   mpoolNames.each { 
      mpoolName -> println "        mpool name = $mpoolName"
   } 
}

结果:

OPERATING SYSTEM:
    OS architecture = amd64
    OS name = Windows 10
    OS version = 10.0
    OS processors = 8

RUNTIME:
    Runtime name = 6164@DESKTOP-UBF4S8B
    Runtime spec name = Java Virtual Machine Specification
    Runtime vendor = Oracle Corporation
    Runtime spec version = 1.8
    Runtime management spec version = 1.2
   
MEMORY:
   HEAP STORAGE:
        Memory committed = 257425408
        Memory init = 268435456
        Memory max = 3790077952
        Memory used = 46437528 NON-HEAP STORAGE:
        Non-heap memory committed = 21168128
        Non-heap memory init = 2555904
        Non-heap memory max = -1
        Non-heap memory used = 20688832
   
GARBAGE COLLECTION:
    name = PS Scavenge
        collection count = 1
        collection time = 3
        mpool name = PS Eden Space
        mpool name = PS Survivor Space
    name = PS MarkSweep
        collection count = 0
        collection time = 0
        mpool name = PS Eden Space
        mpool name = PS Survivor Space
        mpool name = PS Old Gen
Result: [sun.management.GarbageCollectorImpl@2bfc268b, sun.management.GarbageCollectorImpl@2f8dad04]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,646评论 18 139
  • 变量定义 groovy 是动态类型的语言,也就是说不需要指定变量的类型,类型是可以值来推导的。 不指定类型定义变量...
    zachaxy阅读 776评论 0 0
  • 1.在Groovy可以用def定义无类型的变量(定义变量方面def与JavaScript中的var相似),和返回值...
    Alex_1799阅读 685评论 0 0
  • 背景 前两天成功的为Orange pi 编译了USB无线网卡驱动,想起几个月前尝试在Mac下为Orange pi编...
    zhouyufei阅读 1,022评论 0 0
  • 那天开玩班会,我跑回六楼收拾东西,刚到宿舍楼下,周围刮起了凉风,我低下头,风刮过一阵,抬头看见了她。 时隔四年,她...
    云竹chen阅读 111评论 0 0