1、定义类和脚本
1.1、定义成员变量和本地变量
-
定义成员变量, 本地变量
-
/** * 声明变量 * @author liangchen* @date 2020/11/8 */ class DeclareVariableDemo { // 成员变量 public fieldWithModifier String typedField def untypeField protected field1, field2, field3 private assignedField = new Date() static classField public static final String CONSTA = 'a', CONSTB = 'b' static void main(String[] args) { // ClassCastException 类转换异常 final String PI = '3.14' assert PI.class.name == 'java.lang.String' assert PI.size() == 4 GroovyAssert.shouldFail(ClassCastException) { Float areaofCircleRadiusOne = PI } } def someMethods(){ // 本地变量 def localUntypedMethodVar = 1 int localTypedMethodVar = 1 def localVarWithoutAssigment , andAnotherOne } def localvar = 1,boundvar1 = 1 def someMethod(){ def localMethodVar = 1 boundvar2 = 1 } }
-
没有字段默认调用方法
-
/** * 引用成员变量 * @author liangchen* @date 2020/11/8 */ class ReferenceFieldDemo { static void main(String[] args) { def counter = new Counter() counter.count = 1 assert counter.count == 1 def fieldName = 'sum' counter[fieldName] = 2 assert counter.sum == 2 // 没有值,就调用get方法 def pretender = new PretendFieldCounter() assert pretender.isNoField == 'pretend value' assert pretender.count == 0 //调用set方法 count ==1 pretender.isNoFieldEither = 'just to increase counter' // 调用set方法 count==2 pretender.aaa = 1 assert pretender.count == 2 } } class Counter{ public count =0 public sum = 0 } class PretendFieldCounter { public count = 0 Object get(String name) { return 'pretend value' } void set(String name, Object value) { count++ } }
1.2、定义方法和参数
-
可以是确定类型和不确定类型
-
/** * 声明方法 和入参类型 * @author liangchen* @date 2020/11/8 */ class ClassWithTypedAndUntypedMethods { static void main(args) { def some = new ClassWithTypedAndUntypedMethods() some.publicVoidMethod() assert 'hi' == some.publicUntypedMethod() assert 'ho' == some.publicTypeMethod() def classWith = new ClassWithTypedAndUntypedMethodParams() // 入参类型 assert 'untyped' == classWith.method(1) assert 'typed' == classWith.method('whatever') assert 'two args' == classWith.method(1,2) } /** * 没有返回值 */ void publicVoidMethod(){} /** * 没有返回类型方法 * @return */ def publicUntypedMethod(){ return 'hi' } /** * 有返回值类型 * @return */ String publicTypeMethod(){ return 'ho' } private static final void combinedMethod(){} } class ClassWithTypedAndUntypedMethodParams { static void main(args) { } /** * 不确定类型入参 * @param arg * @return */ static method(arg){ return 'untyped' } /** * 有类型入参 * @param arg * @return */ static method(String arg) { return 'typed' } /** * 两个参数 * @param arg1 * @param arg2 * @return */ static method(arg1, Number arg2) { return 'two args' } }
-
map, list 数组入参
-
/** * list map 入参 * @author liangchen* @date 2020/11/9 */ class Summer { static void main(String[] args) { def summer = new Summer(); assert 2 == summer.sumWithDefualts(1,1) assert 3 == summer.sumWithDefualts(1, 1, 1) assert 2 == summer.sumWithList([1,1]) assert 3 == summer.sumWithList([1,1,1]) assert 2 == summer.sumWithOptionals(1,1) assert 3 == summer.sumWithOptionals(1,1,1) assert 2 == summer.sumNamed(a:1, b:1) assert 3 == summer.sumNamed(a: 1, b: 1, c: 1) assert 1 == summer.sumNamed(c:1) } def sumWithDefualts(a, b, c = 0) { return a + b + c } def sumWithList(List args) { return args.inject (0){sum, i -> sum +=i} } def sumWithOptionals(a, b, Object[] optionals) { return a + b + sumWithList(optionals.toList()) } /** * 入参为map * @param args * @return */ def sumNamed(Map args) { // 不存在设置0 ['a','b','c'].each {args.get(it, 0)} return args.a + args.b + args.c } }
-
1.3、?. 判断是否连续为空 (短路运算符)
-
避免连续判空
-
/** * ?. 避免空指针,连续判空 * @author liangchen* @date 2020/11/9 */ class ProtectionNPEs { static void main(String[] args) { def map = [a: [b: [c: 1]]] assert map.a.b.c ==1 if (map && map.a && map.a.x) { assert map.a.x.c == null } try { assert map.a.x.c == null } catch (NullPointerException ignore) { } assert map?.a?.x?.c==null } }
-
1.4、构造器
-
指定成员变量名和其他方式
-
/** * @author liangchen* @date 2020/11/9 */ class CallConstructorDemo { String name, product CallConstructorDemo(name, product) { this.name = name this.product = product } // Java 的方式 def first = new CallConstructorDemo('Canoo', "ULC") // as 语法 def second = ['Canoo','ULC'] as CallConstructorDemo // 自己数组元素 CallConstructorDemo third = ['Canoo', 'ULC'] } class CallConstructorNameDemo{ String name, product public static void main(String[] args) { // 可以指定成员变量名 new CallConstructorNameDemo() new CallConstructorNameDemo(name: 'Canoo') new CallConstructorNameDemo(product:'ULC') new CallConstructorNameDemo(name: 'Canoo', product: 'ULC') } }
-
2、组织类和脚本
2.1、文件与类关系
-
一个文件有多个类
-
/** * 一个groovy 有两个类 * @author liangchen* @date 2020/11/9 */ class MultipleClassDemo { static void main(String[] args) { def canoo = new Vendor() canoo.name = 'jack' canoo.product='apple' canoo.address.street = '天顶乡' canoo.address.zip = 1121 canoo.address.town = '岳麓区' canoo.address.state = '长沙' // 查找匹配字符 assert canoo.dump() =~ /apple/ // 查找匹配字符 assert canoo.address.dump() =~/1121/ println canoo.address.dump() } } class Vendor { public String name public String product public Address address =new Address(); } class Address{ public String street, town , state public int zip }
-
2.2、在包组织类
-
跟java类似
-
默认导入语句
-
import java.lang.* import java.util.* import java.io.* import java.net.* import groovy.lang.* import groovy.util.* import java.math.BigInteger import java.math.BigDecimal
-
-
导入设置别名 ( 避免相同类名,不同包下,识别更快)
-
需要继承类
-
package com.jack.groovy.ch7.thirdparty /** * @author liangchen* @date 2020/11/10 */ class MathLib { Integer twice(Integer value) { return value * 3 } Integer half(Integer value) { return value / 2 } }
-
继承类
-
package com.jack.groovy.ch7 // 这里使用 as 为这个导入设置别名 import com.jack.groovy.ch7.thirdparty.MathLib as TypeMathLib /** * @author liangchen* @date 2020/11/10 */ class MathLib extends TypeMathLib { /** * 订正 2倍 * @param value * @return */ Integer twice(Integer value) { return value * 2 } static void main(String[] args) { def mathlib = new MathLib() assert 10 == mathlib.twice(5) assert 2 == mathlib.half(5) } }
-
-
2.3、考虑更深classpath(类路径)
3、面向对象的高级特性
3.1、使用继承
- 类似java
3.2、使用接口
- 类似java
3.3、多方法(重载)
-
方法名一样,入参不一样
-
/** * 方法重载 * @author liangchen* @date 2020/11/10 */ class Multimethod { def oracle(Object o) { return 'object' } def oracle(String o) { return 'string' } static void main(String[] args) { def multi = new Multimethod() Object x =1 Object y = 'foo' assert 'object' == multi.oracle(x) assert 'string' == multi.oracle(y) } }
3.4、使用trait
-
trait 关键字
-
/** * trait 有点类似 接口,只不过他有一些方法和属性, 应该说是抽象类和接口结合体 * @author liangchen* @date 2020/11/10 */ class TraitDemo { trait HashId{ long id } trait HasVersion{ long version } trait Persistent{ boolean save(){ println "saving ${this.dump()}" } } trait Entity implements Persistent ,HashId, HasVersion{ boolean save(){ version++ Persistent.super.save() } } class Publication implements Entity{ String title } class Book extends Publication{ String isbn } static void main(String[] args) { Entity gina = new Book(id:1,version: 1,title: 'gina', isbn: "11111") gina.save() assert gina.version == 2 } }
4、GroovyBeans使用
4.1、声明bean
-
/** * groovy bean 定义 * @author liangchen* @date 2020/11/10 */ class MyBeanDeom { static class MyBean implements Serializable{ String myprop //没有定义类型 def untyped //定义类型 String typed def item1, item2 //赋值初始值 def assigned = 'default value' } static void main(String[] args) { MyBean myBean = new MyBean() assert 'default value' == myBean.getAssigned() myBean.setUntyped('some value') assert 'some value' == myBean.getUntyped() } }
4.2、beans运行特征
-
获取field(成员变量)和方法
-
/** * 调用groovy方法 * @author liangchen* @date 2020/11/10 */ class CallGroovyWayDemo { static class MrBean { String firstname, lastname String getName (){ return "$firstname $lastname" } } static void main(String[] args) { def bean = new MrBean(firstname: 'Rowan') bean.lastname = 'Jack' // 自动调用name --> getName 方法 assert 'Rowan Jack' == bean.name //获取成员变量,使用.@ def beanss = new DoublerBean(value: 100) assert 200 == beanss.value assert 100 == beanss.@value } /** * 获取成员变量,使用.@ * */ static class DoublerBean { public value void setValue(value) { this.value = value } def getValue() { value * 2 } } }
-
4.3、在任何类中使用bean 的方法
-
获取def 修饰的field 字段
-
/** * 获取bean的属性 * 获取def 修饰的变量 * @author liangchen* @date 2020/11/10 */ class GDKBeanProperties { static class ClassWithProperties{ def someProperty public someField private somePrivateField } static void main(String[] args) { def obj = new ClassWithProperties() def store = [] obj.properties.each { property -> store += property.key store += property.value } assert store.contains('someProperty') assert store.contains('someField') == false assert store.contains('somePrivateField') == false assert store.contains('class') assert obj.properties.size() == 2 } }
-
4.4、Field、accessors、maps and Expando
-
Expando
-
/** * 动态扩展属性和方法 Expando * @author liangchen* @date 2020/11/10 */ class ExpandoDemo { static void main(String[] args) { def boxer = new Expando() assert null == boxer.takeThis // 赋值 takeThis 不存在的值 boxer.takeThis = 'jack' assert 'jack' == boxer.takeThis // 定义方法 boxer.fightBack = {times -> delegate.takeThis * times} assert 'jackjack' == boxer.fightBack(2) } }
-
5、使用高级语法特性
5.1、使用GPaths查询对象
-
/** * GPath 解析 * @author liangchen* @date 2020/11/10 */ class GPathInvoiceDemo { static class Invoice{ List items Date date } static class LineItem{ Product product int count int total(){ return product.dollar * count } } static class Product { String name def dollar } static void main(String[] args) { def ulcDate = Date.parse('yyyy-MM-dd', '2015-01-01') def otherDate = Date.parse('yyy-MM-dd', '2015-02-02') def ulc = new Product(dollar: 1499, name: 'ULC') def ve = new Product(dollar: 499, name: 'Visual Editor') def invoices = [ new Invoice(date: ulcDate, items: [ new LineItem(count: 5, product: ulc), new LineItem(count: 1, product: ve) ]), new Invoice(date: otherDate, items: [ new LineItem(count: 4, product: ve) ]) ] // lineItem 平铺,拆开 def allItems = invoices.items.flatten() // 循环调用 total方法 assert [5*1499, 499, 4*499] == allItems*.total() // 查询 数量大于 7000的 assert ['ULC'] == allItems.grep{it.total() > 7000}.product.name // product == ulc , date日期变成字符串 def searchDates = invoices.grep { it.items.any{it.product == ulc}}.date*.toString() assert [ulcDate.toString()] == searchDates } }
5.2、注入*操作
-
/** * * 号操作 * @author liangchen* @date 2020/11/10 */ class SpreadDemo { def getList(){ return [1,2,3] } def sum(a, b, c) { return a + b + c } static void main(String[] args) { def spread = new SpreadDemo() // 直接调用getList 方法获取到值作为sum的参数 assert 6 == spread.sum(*spread.list) // 直接使用*变量数组 def range = (1..3) assert [0,1,2,3] == [0, *range] // 或者map 或者map *:map def map = [a:1, b:2] assert [a:1, b:2, c:3] == [c:3, *:map] } }
5.3、利用命令链来使用精确语法
6、总结
- 方法、成员变量、局部变量定义(对比java来说的)
- groovybean定义