Groovy系列一 Groovy基础语法

news/2024/11/20 17:36:41/

目录

为什么要学习Groovy

Groovy 介绍

Groovy 特点

Groovy 实战

动态类型

简单明了的list,map类型

在groovy世界任何东西都是对象

属性操作变得更容易

GString

闭包

委派:delegate

Switch变得更简洁

元编程

强制类型检查

Elvis Operator

安全访问


为什么要学习Groovy

        作为Java为主语言的程序员,Groovy作为Java平台上的脚本语言(动态语言)在兼容方面是有得天独厚的优势。接触过Aandroid开发的同学大家都已经接触到啦Gradle构建项目(Gradle构建也支持Java项目的构建),Gradle就是采用Groovy实现的用于构建项目的框架。还有就是新版本的idea推荐使用Gradle进行插件开发。当然以上只是从客观方面阐述Groovy技术的发展趋势(包含但不仅限于这些方面)来说明我们需要学习,从自身层面来说多学多益,或者说有技术追求或者技术理想的同学,多学一门技术也是对自己的提升。接下来就让我们一起走进Groovy的世界吧。

Groovy 介绍

        Apache Groovy是一种强大的、可选的类型和动态语言,具有静态类型和静态编译功能,用于Java平台,旨在通过简洁、熟悉和易于学习的语法提高开发人员的生产力。它可以与任何Java程序顺利集成,并立即为您的应用程序提供强大的功能,包括脚本功能、领域特定语言创作、运行时和编译时元编程以及函数式编程。

                                                                                                                           -- groovy 官网

        以上是官网介绍,我个人的通俗理解如下,Groovy是用于Java虚拟机的一种敏捷的动态语言,是一种成熟的面向对象编程语言,又是一种纯粹的脚本语言。Groovy运行在JVM环境上,在语法上兼具java 语言和脚本语言特点,大大简化了语法。同时又具有闭包和动态语言中的其他特性,弥补了单纯的Java代码所不具备的动态性,我们可以在程序运行时任意修改代码逻辑,不需要重新发布。

        Groovy 1.0于2007年1月2日发布。 Groovy通过Apache License v 2.0发布。Groovy的官方网站是The Apache Groovy programming language

Groovy 特点

        Groovy中有以下特点(官网API文档:The Apache Groovy programming language - Groovy Development Kit):

  1. Groovy是基于Java虚拟机的一种面向对象的脚本语言,同时支持静态和动态类型。
  2. Groovy对于Java开发人员来说很简单,因为Java和Groovy的语法非常相似,可以使用现有的Java库。
  3. 支持运算符重载。
  4. 本地语法列表和关联数组。
  5. 对正则表达式的本地支持。
  6. 各种标记语言,如XML和HTML原生支持。
  7. Groovy扩展了java.lang.Object。

Groovy 实战

动态类型

        groovy的第一个特性就是动态特性,定义一个变量以后,可以对这个变量赋与任何类型的值;groovy提供了这种支持方式但是出于好的编码习惯而言,我们是杜绝这种开发方式的。

def v = 0;//定义了数值类型的变量v 
v = new Date();//然后又给它赋与Date类型的值. 
println(v);

简单明了的list,map类型

        我们可以使用groovy简单明了的定义list和map数据结构。不像在Java中国我们要先定义类型才能赋值,Groovy直接使用语法糖就可以快速赋值。具体看如下的代码事例,只列举了其中典型的API进行概念说明,剩余的API如果同学们感兴趣可以自行尝试练习。

  • 使用"[]"定义list列表,并对其直接操作
// list 可以看到的是编译器帮我们作何类型识别
def list = [1, 2]
// 这个是groovy的list的API从左边插入一个记录
list.leftShift(3)
// push是从插入到列表前面
list.push(0)
// add和我们java的List一样是追加到最后
list.add("abc")
// groovy中的<<可以对list数据类型的作用添加值,也是追加到最后面,需要注意的是在数字类型时是位运算操作
list << "<<号";
// "+"在groovy的语法中也是追加元素到集合中,并且是追加到最后
list += "加上+="// 查看打印结果可以看到我在每个API的功能描述上的说明
// [0, 1, 2, 3, abc, <<号, 加上+=]
println(list)// 也可以采用 lambda 表达式遍历集合
list.forEach({ println(it)})
  • 使用":"分隔key和value来定义map数据,key不需要用引号引起来,并且能使用key直接对map进行读写操作
def map = [a: 2, b: new Date()];// 写入 直接追加到map集合中
map.put("aaaa","bbb")println(map)
// 写入 直接采用Map的key进行操作
map.a = "a value change"println(map)// 结果如下 可以看到 key 为 "a" 的value被改变
[a:2, b:Sun May 28 11:19:56 CST 2023, aaaa:bbb]
[a:a value change, b:Sun May 28 11:19:56 CST 2023, aaaa:bbb]

在groovy世界任何东西都是对象

        怎么理解上面的概念呢,对照着Java语言来说,我们都知道在Java语言中有是区分对待基本类型和引用类型的。基本类型是没有方法调用的因为基本类型是按值访问的,在这个方面Groovy比Java更像是一个面向对象语言。

// 在groovy中,一切都是对象。一切都可以当成对象来使用;
// 即使在Java中的基本类型也更像是一个对象
100.times {println("hello world")}

属性操作变得更容易

        不同于Java中要操作一个对象中的属性必须通过get,set方法,即使是将属性定义成private。在groovy中,定义一个javabean,不再需要写getter,setter方法。读写属性直接用"."号操作即可。

class JavaBeans {String a// 即使是定义成private 也可以直接访问//    private String a
}def beans = new JavaBeans();beans.a = "object set property value"println(beans.a)

GString

        GString是Groovy提供的快速处理字符串的工具。双引号""号的下字符串,可以直接通过 $var 或者 ${var}方式简单明了的嵌入变量。并且GStrng会调用包含的闭包 无参GString会调用闭包并打印我们期待的结果到Writer。

// case1
def a = "a"
def b = "b"
// a=a,b=b 快速替换字符串变量
println("a=${a},b=$b")// case2
def name = 'lly'
def hello = "hello $name !"
// 结果:hello lly ! 快速替换字符串变量
println hello
// 注意这一行
name = '阳仔'
// 结果:hello lly !
println hello// case3 :GStrng会调用包含的闭包 无参GString会调用闭包并打印我们期待的结果到Writer
def quote = "${-> name} , welcome"
// 结果:阳仔 , welcome
println quote
// 注意这一行
name = 'lisi'
// 结果:lisi , welcome
println quote

闭包

        在groovy中的闭包可以看成是一个代码块,它可以没有参数和返回值;它像java8以上的lambda语法或者像一个有一个方法的java内部类(这里类似于函数式编程规范定义)。在groovy闭包中的隐含内置变量,通过哪住的变量我们可以做一些获取单独元素操作的事情。比如迭代、判断等等其他业务。

it:当闭包的方法中,没有定义任何参数时,也可以直接用it变量;

this:跟java中的this一样;

owner:基本上跟this一样,只是除了一种情况,如果该闭包是在其他的闭包中定义的,owner就指向定义它的闭包对象。

// 闭包中内置了很多迭代方法,如find、findAll、collect等等。这里需要注意的是内置对象 it 的使用
def list = ['foo', 'bar']
def newList = []
list.collect(newList) {it.toUpperCase()
}
// 结果:[FOO, BAR]
println newList//或者
list = ['foo', 'bar']
newList = []
list.collect(newList, {it.toUpperCase()
});
// 结果:[FOO, BAR]
println newList// 在groovy闭包中的隐含内置变量def a = {println "a this:" + thisprintln "a owner:" + owner // ower指向bdef b = {println "b this:" + thisprintln "b owner:" + owner // ower指向b}b.call()}
a.call()// 结果:这里可以看到 this 和 owner 异同
a this:script.GroovyDemo1@78b236a0
a owner:script.GroovyDemo1@78b236a0
b this:script.GroovyDemo1@78b236a0
b owner:script.GroovyDemo1$_run_closure3@304b9f1a

委派:delegate

        Groovy中的delegate基本上是跟owner的一样,除非它通过Closure.setDelegate()委派指向新的对象。

def scriptClosure = {println "scriptClosure this:" + thisprintln "scriptClosure owner:" + ownerprintln "scriptClosure delegate:" + delegate
}
println "before setDelegate()"
scriptClosure.call()
scriptClosure.setDelegate("lly")
println "after setDelegate()"
scriptClosure.call()// 结果:
scriptClosure this:script.GroovyDemo1@5c371e13
scriptClosure owner:script.GroovyDemo1@5c371e13
scriptClosure delegate:script.GroovyDemo1@5c371e13
after setDelegate()
scriptClosure this:script.GroovyDemo1@5c371e13
scriptClosure owner:script.GroovyDemo1@5c371e13
scriptClosure delegate:lly

Switch变得更简洁

        Groovy中的switch可以允许专入list,对象,范围...等表达式作为case依据

def x = 20;
switch (x) {case [1, 2, 3, 4, 5]:println("aaaaaa")break;case "foo":println("bbbbb")case 10..1000:println("ccccc")break;case Date:println("dddddd")break;
}// 结果: 因为 20 在 10到1000 的范围内
ccccc

元编程

        在Groovy中,可以使用 metaClass类来,对元对象添加属性和方法。原因是由于在Groovy中,如果你的对象使用了一个它不曾定义过的方法不会报错,至少编译的时候不会报错,这就是因为Groovy特殊的运行时机制。你调用了一个对象的方法,他会先去检查这个类里面是否定义了这个属性和方法。如果没有的话会去MeteClass中去寻找,在Java中所有的类都会集成Object,而在Groovy中,所有的类都会继承GroovyObject,这个类里面就有获取MeteClass的方法。这样,就可以在运行中去动态的给对象添加属性和方法,甚至是静态的方法。如果MeteClass中也没有定义这个方法的话,就要去依次去寻找实体类里面是否实现了methodMissing和invokeMethod方法了,在这两个方法里面可以做特殊的处理。

// 基本元编程
// 对String类,添加一个uppers方法
String.metaClass.uppers = { -> toUpperCase() };
println "aaa".uppers()
//结果:AAA// 对Interger类,添加一个say方法
Integer.metaClass.say = { -> "I am Interger" }
def i = new Integer(100);
println i.say()
// 结果:I am Interger// 给对象添加属性、方法、静态方法
class Person {String name;Integer age;String eat() {println(name + "like eat")}
}
def p = new Person(name: "阳仔", age: 18)
p.eat()// 给对象添加属性
p.metaClass.sex = '男'
// 给对象添加方法
p.metaClass.drink = {-> println "喜欢喝饮料"
}
// 给对象添加静态方法
p.metaClass.static.play = {-> println "喜欢玩游戏"
}println "${p.name},今年${p.age}岁了,性別是${p.sex}"
p.drink()
p.play()// 结果
阳仔like eat
阳仔,今年18岁了,性別是男
喜欢喝饮料
喜欢玩游戏

强制类型检查

        在之前的咱们的学习过程中发现,Groovy都是弱类型检查,不管是变量还是集合都可以接收任何类型的数据,如果我们想要在某些场景中限制某种类型就要用到@TypeChecked注解尽兴强制类型检查。在闭包中,如果需要强类型检查,可以像java语法一样定义参数类型。

class Foos{int  i = 42.0; //编译通过
}@TypeChecked
class Foo{int  i = 42.0; //编译不通过
}//在闭包中,如果需要强类型检查,可以像java语法一样定义参数类型
def list = ["a","b","c"]
// 编译不通过
//def list = ["a","b","c", 1]
list.collect {String it -> it.toUpperCase()
}
println(list)

Elvis Operator

        Groovy中采用Elvis Operator 运算,进一步简化三元运算符。

def a = null;
// 在定义b变量时,先判断a是否有值,如果有,就取a的值作为b的值,否则就取值"b"
def b = a ?: "b"; 
println(b)

安全访问

        跟我们Java中判空一样,只不过更加简洁而已。

def person;
//先判断person是否为不为null,然后,再调用getName方法
String name = person?.getName();
println(name)


http://www.ppmy.cn/news/98444.html

相关文章

Vue与React更应该学哪一个

Vue和React都是当前最流行的前端框架之一。但是对于那些新手来说&#xff0c;很难决定哪一个框架更适合自己。本文将对Vue和React进行详细介绍和比较&#xff0c;以帮助你更好地选择一个框架。 一、Vue.js Vue是由中国大陆程序员尤雨溪所开发的一个渐进式JavaScript框架&…

C++无锁队列

C无锁队列是一种多线程编程技术&#xff0c;它可以在不使用锁的情况下实现线程安全的队列。它可以提高多线程程序的性能。 无锁队列的主要思想是让多个线程同时访问队列&#xff0c;而不需要使用锁来保护共享资源。这可以避免锁竞争和死锁等问题&#xff0c;从而提高程序的效率…

Android 12.0关机界面全屏显示(UI全屏显示)

1.概述 在12.0的系统定制化开发中,原生系统关机界面 UI是靠右边显示的,但是客户需求要求全屏显示 重启和关机功能键居中显示,所以就涉及到调整UI 然后全屏显示,需要实现窗口的全局布局实现全屏功能 2.关机界面全屏显示(UI全屏显示)的核心类 frameworks / base / packa…

2023-05-28 mysql列存储引擎-外表与两表内连接进行外连接处理-分析

摘要: 最近在处理一个外连接与两表内连接查询过于缓慢的问题, 一个明显的对比是外表进行内连接的耗时极短。 本文对该场景和问题的发生做分析。 DML 表结构 create table b(b1 int, b2 varchar(2), primary key(b1)) engine=tianmu;create table a(a1 int, a2 varchar(2), fo…

【重新定义matlab强大系列十一】函数rescale数组元素的缩放范围

&#x1f517; 运行环境&#xff1a;Matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 #### 防伪水印——左手の明天 #### &#x1f497; 大家好&#x1f917;&#x1f91…

以太坊学习三: Merkle树和验证

Merkle tree简介 Merkle树又称为哈希树&#xff0c;是一种二叉树&#xff0c;由一个根节点、若干中间节点和一组叶节点组成。最底层的叶节点存储数据&#xff0c;在它之上的一层节点为它们对应的Hash值&#xff0c;中间节点是它下面两个子节点的Hash值&#xff0c;根节点是最后…

PriorityQueue优先级队列

前言 优先级队列就是在堆的基础上进行改造&#xff0c;那么什么是堆&#xff0c;又什么是优先级队列呢&#xff1f; 我们一起来看看吧&#xff01; 目录 前言 一、堆 &#xff08;一&#xff09;堆的创建 &#xff08;二&#xff09;堆的插入 &#xff08;三&#xff09;堆…

【自然语言处理】不同策略的主题建模方法比较

不同策略的主题建模方法比较 本文将介绍利用 LSA、pLSA、LDA、NMF、BERTopic、Top2Vec 这六种策略进行主题建模之间的比较。 1.简介 在自然语言处理&#xff08;NLP&#xff09;中&#xff0c;主题建模一词包含了一系列的统计和深度学习技术&#xff0c;用于寻找文档集中的隐…