Groovy 之基础语法,闭包(上)

简介: Groovy 之基础语法,闭包(上)

基本类型


其实在 Groovy 中是没有基本类型的,例如下所示:


int x = 10;
println(x.class)


打印结果如下:


class java.lang.Integer


可以看到他是一个 Integer 对象。其实在底层编译的时候已经将 int 装箱成了 对象。


变量的定义


groovy 定义变量有两种方式,分别是 强类型定义 和 若类型定义,强类型定义和 java 中的意义,但是弱类型定义是什么呢,如下:


//强类型定义方式
int x = 10;
println(x.class)
//弱类型定义方式
def x1 = 1;
println(x1.class)
def x2 = 3.14;
println(x2.class)
def x3 = "Android"
println(x3.class)


结果如下:


class java.lang.Integer
class java.lang.Integer
class java.math.BigDecimal
class java.lang.String


第二行 是大数据类型


其实弱类型定义就是不指定具体的类型。通过值来确定它到底是什么类型。用 def 来定义


如何选择呢?如果在本类中使用,则建议使用 def 类型。但是别的类也要用到这个变量。则尽量使用强类型定义;def 声明的变量类型可以随时改变,如 x1 是 Integer 。如果给 x1 赋值为 String,这样他就会变为 String。正是这个原因所以才不建议在 别的类使用这个变量时定义为 def。


字符串


常用的定义方式:


//1,通过 单引号定义String ,和双引号没有任何区别 ,转义 '单引号 \'String \''
def name = '单引号 String'
println(name)
//2,通过三个单引号定义String ,但定义的格式进行输出,
def name1 = '''第一行
第二行
第三行'''
println(name1)
// 3,双引号 ,可扩展字符串,扩展后使用的不是String,而是GString类
def name2 = "双引号"
def hello = "hello ${name2}"
println(name2)
println(hello.class)
//可扩展字符串使用 ,可以扩展任意的表达式
def sum = "sum = ${5 - 6 - 6 + 12}"
println(sum)
def result = echo(sum)
println(result)
String echo(String message){
    return message;
}


通过上面这几种方式可以 定义字符串,其实一般最常用的就是 第三种了。注意扩展后的字符串就不是 String。而是 GString。不信的话可以打印看一下。


字符串方法


字符串的方法

1,第一种就是String类原有的方法

2,第二种则是 DefaultGroovyMethods ,是 Groovy 对所有对象的扩展

3,第三种是 StringGroovyMethods ,继承自 DefaultGroovyMethods 。


重点要看的是 StringGroovyMethods 。他继承自第二种,第一种是 String,比较熟悉。


首先定义一个字符串:


String str = "哈哈哈"


填充


println str.center(8, 'a') //填充: aa哈哈哈aaa
println str.padLeft(8, 'a') //填充:aaaaa哈哈哈


比较


println str > "嘻嘻嘻" //通过运算符比较字符串大小 :false


索引


println str.getAt(0) //下标为0 :哈
println str[0]  //通过类似于数组的方式来获取 :哈
println str[0..1] //指定范围 :哈哈


减法


println str.minus("哈哈") //减法 : 哈  --减去两个剩一个 。
println str - "哈哈";


倒序


println str.reverse()


首字母大写


println str.capitalize()


判断 str 是否为数字类型


println str.isNumber()


转为基本数据类型


println str.toInteger()
println str.toBoolean()
println str.toDouble()


其实方法还有很多,这里就不一一列举了。


可查看文档


控制语句


switch:groovy 中的 switch 和 java 中的有明显的不同,它可以接受任意的数据类型。如下:


// switch ,可以传入任意类型的数据
def x = 1.23
def result;
switch (x) {
    case '哈哈哈哈':
        result = '0'
        break
    case '嘻嘻':
        result = '1'
        break
    case [4, 5, 6, 'inlist']: //列表
        result = '2'
        break
    case 12..30: //范围
        result = '3'
        break
    case Integer:
        result = '4'
        break
    case BigDecimal:
        result = '5'
        break
    default:
        result = 'defalut'
        break
}
println result //5


for 循环


// 对范围的 for 循环
def sum = 0
for (i in 0..9) {
    sum += i
}
println sum
//对 list 进行循环
sum = 0
for (i in [1, 2, 3, 4, 5, 6, 7, 8, 7]) {
    sum += i
}
println sum
//对 map 进行循环
sum = 0;
for (i in ['one': 1, 'two': 2, "three": 3]) {
    sum += i.value
}
println sum; 
// 45
// 43
// 6


闭包


基础详解


闭包是一个开放的,匿名的代码块,可以带参数,返回一个值。可以通过一个变量引用到他,也可以传递给别人进行处理。


闭包的创建和调用


def clouser = {
    println "hello groovy"
}
//两种方式调用闭包
clouser.call()  // hello groovy
clouser()  // hello groovy


创建带参数的闭包和调用


def clouser = {
        //箭头前面是参数,后面是闭包体
    String name, int age ->
        println "hello groovy ${name} -- ${age}"
}
//调用带参数闭包
clouser.call("张三", 32)  // hello groovy 张三 -- 32
clouser("李四", 23)  //hello groovy 李四 -- 23


默认参数


//每一个闭包都有一个默认的 it 参数,如果不想使用,则显示的定义即可。
def clo = {
    println "hello ${it}"
}
clo.call("李四")  //hello 李四


闭包返回值


def clouser = {
        //箭头前面是参数,后面是闭包体
    String name, int age ->
        return "hello groovy ${name} -- ${age}"
}
//调用带参数闭包
println clouser.call("张三", 32) //hello groovy 张三 -- 32


使用详解


基本类型结合使用:


阶乘


int x = 5
println fab(x)
//求 number 的阶乘
int fab(int number) {
    int reslut = 1
    //调用 upto 方法,传入 number 和 闭包 ,闭包中有一个 num 参数
    1.upto(number, { num -> reslut *= num })
    return reslut
}
//结果:120


为什么要这样写呢?看一下源码秒懂!


//打眼一看这里需要三个参数,我们只传了两个?,注意:1.upto()中的 1,代表的是第一个参数,
public static void upto(Number self, Number to, @ClosureParams(FirstParam.class) Closure closure) {
  //拿到开始的位置和结束的位置
        int self1 = self.intValue();
        int to1 = to.intValue();
        //小于等于
        if (self1 <= to1) {
            for (int i = self1; i <= to1; i++) {
              //调用传入的闭包,将i 传进去,从这里就可以知道我们写的闭包为啥要一个 num 的参数了。
                closure.call(i);
            }
        } else
            throw new GroovyRuntimeException("The argument (" + to +
                    ") to upto() cannot be less than the value (" + self + ") it's called on.");
    }


阶乘2


int fab2(int number) {
    int result = 1
    number.downto(1) {
        num -> result *= num
    }
    return result
}
//结果:120


你知道 downto 方法传入了几个参数吗。。。。没错,是3个,number是一个,1 是一个,括号外面的闭包是一个。闭包写在括号外面和写在里面效果完全一样。这个是倒着来的。具体的可以查看源码。


累加


int cal(int number) {
    int result
    // times 只有两个参数,所以可以使用这种方式来写 ,具体的实现可以看源码,非常简单
    number.times {
        num -> result += num
    }
    return result;
}


字符串的结合使用


定义一个字符串:


String str = "the 2 and 3 is 5"
1
each 遍历
str.each {
    String temp ->
        print temp  //the 2 and 3 is 5
}
//看一下 each 方法的源码
public static <T> T each(T self, Closure closure) {
      //第一个是迭代器,第二个则是闭包了
        each(InvokerHelper.asIterator(self), closure);
        return self;
    }
public static <T> Iterator<T> each(Iterator<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure closure) {
      //遍历 字符串,
        while (self.hasNext()) {
            Object arg = self.next();
            //调用闭包,传入了一个参数,从这里就可以知道我们在定义闭包的时候需要加一个参数
            closure.call(arg);
        }
        return self;
    }


查找符合条件的第一个


println str.find {
    String s ->
      //返回 boolean 。是否符合条件,这里的条件为:是否是数字
        s.isNumber() 
}
//结果:2 ,第一个符合结果的是2,看一下源码
    public static Object find(Object self, Closure closure) {
        //将闭包弄成了 boolean 类型的
        BooleanClosureWrapper bcw = new BooleanClosureWrapper(closure);
        //迭代
        for (Iterator iter = InvokerHelper.asIterator(self); iter.hasNext();) {
            Object value = iter.next();
            //调用闭包,如果返回 true。则表示满足条件,接着就将 value 返回,然后就退出了。不在执行
            if (bcw.call(value)) {
                return value;
            }
        }
        return null;
    }
//查找全部
println str.findAll {
    String s ->
        return s.isNumber()
}
//结果:[2, 3, 5] ,查看源码可知找到后会存在集合中,最后进行返回


判断是否包含数字


println str.any {
    String s ->
        return s.isNumber() // true
}
//源码可自行查看


字符串是否每一项都为数字


println str.every {
    String s ->
        s.isNumber() //false
}
//源码
public static boolean every(Object self, Closure predicate) {
      return every(InvokerHelper.asIterator(self), predicate);
}
public static <T> boolean every(Iterator<T> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure predicate) {
        BooleanClosureWrapper bcw = new BooleanClosureWrapper(predicate);
        while (self.hasNext()) {
            //是否满足闭包中的条件
            if (!bcw.call(self.next())) {
                return false;
            }
        }
      //循环完成后表示都满足条件,返回true
        return true;
    }


将字符串转为集合


println str.collect {
    //将 字符转换大写
    it.toUpperCase()
}
//查看源码
 public static <T> List<T> collect(Object self, Closure<T> transform) {
      //这里创建了一个新的集合
      return (List<T>) collect(self, new ArrayList<T>(), transform);
 }
public static <T> Collection<T> collect(Object self, Collection<T> collector, Closure<? extends T> transform) {
      //给字符串加上迭代器
        return collect(InvokerHelper.asIterator(self), collector, transform);
}
  public static <S,T> Collection<T> collect(Iterator<S> self, Collection<T> collector, @ClosureParams(FirstParam.FirstGenericType.class) Closure<? extends T> transform) {
        while (self.hasNext()) {
            //调用闭包中的方法,将返回的结果保存到集合中
            collector.add(transform.call(self.next()));
        }
        //返回集合
        return collector;
    }


相关文章
|
4月前
|
人工智能 Dart Java
Kotlin基础语法
Kotlin基础语法
Groovy 之基础语法,闭包(下)
Groovy 之基础语法,闭包(下)
|
JSON Java C#
Groovy核心语法总结
Groovy是一种基于JVM,功能强大、类型可选,动态的、可与Java无缝衔接的编程语言。Groovy语法简洁、易于学习,可以大大提高开发人员的工作效率,可为Java程序添加强大的功能,包括脚本功能、特定领域的语言编写、运行时和编译时元编程以及函数式编程。本文将快速介绍核心语法,让读者快速入门。
1188 0
 Groovy核心语法总结
|
Java Kotlin 编译器
Kotlin 基础语法
Kotlin 文件以 .kt 为后缀。 包声明 包的声明应处于源文件顶部: package my.demo import java.util.* // …… kotlin源文件不需要相匹配的目录和包,源文件可以放在任何文件目录。
1022 0
|
自然语言处理 Java
|
Java 索引 Kotlin