groovy学习历程(第二章,面向java的groovy)

一,java和groovy的区别点

//进行系统级进程交互
println "git help".execute().text
//当在string实例上调用execute()方法时,groovy创建了一个扩展了java.lang.Process的类的实例,就像java代码中runtime类的exec()方法所做的那样
println "groovy -v".execute().getClass().name
//调用查看groovy版本号
println("groovy -v".execute().text)

groovy的for循环有多种写法

//groovy的for循环写法
for (i in 0..3){
    println("好困鸭")
}
//for循环的写法2
0.upto(3){
    println("$it")
}
//for循环的写法3
3.times {
    println("$it")
}
println("@@@@@@@@@@@")

/***
 * 选择在循环是跳过一些值
 * 10是最大值,3是叠加数
 */
0.step(10,3){
    println("$it")
}


在这个方法中,foo()的?.操作符只有在引用不为null的时候才会调动指定方法或属性

//if的另一种写法
def foo(str){
  //if (str!=null){str.reverse()}
    str?.reverse()
}
println foo("evil")
println(foo(null))

异常处理
异常可以不处理,groovy中是自动抛出给更高一层

def openFile(def fileName){
    new FileInputStream(fileName)
}
//异常处理和捕获
try {
    openFile("nonexistentfile")
} catch (FileNotFoundException f) {
    println("Oops:"+f)
}

但是要注意的是,他不能捕获Exception之外的Error或Throwwable。要捕获这些,需要使用catch(Throwable throwable)
groovy是轻量级的java,
方法和类是默认公开的(public)
?.操作符只有对象引用不为空时才会分派调用
静态方法内可以使用this来引用class的对象

二,javabean
groovy的class写法可以更简便一些
groovyCar.groovy

class Car {
    def milse = 0
    final year

    Car(theCar) { year = theCar }
}

groovy.Car car = new groovy.Car(2008)
println("year:$car.year")
println("milse:$car.milse")
println("setting milse")
car.milse=25
println("milse: $car.milse")

在groovy中,get和set方法是默认创建的,不可见。(就像在java中,空参的构造方法是默认创建的一样)
在程序调用milse时,应用的不是一个字段,而是他的get。要把属性设置为只读的时候,需要用final来声明该属性,和java一样
final是不可更改的,修改final的字段任何尝试都会导致异常。因此,如果要把变量设置为私有的,必须实现一个拒绝任何修改的更改器。

GroovyCar2.groovy
class Car {
    final year
    private milse = 0
//相当于构造方法
    Car(theCar) { year = theCar }

    def getMilse() {
        println("getMilse  called")
        milse
    }

    private void setMilse(milse) {
        throw new IllegalAccessException("you're not allowed to change milse")
    }

    def drive(dist) {
        if (dist > 0) milse += dist
    }

}

这里使用final声明year,使用private声明milse,在drive()实例方法中,无法修改year,但是可以修改milse.milse的set()方法不允许在类的外部对该属性的值进行修改

package groovy

class Car2 {
    final year
    private milse = 0
//相当于构造方法
    Car2(theCar) { year = theCar }

    def getMilse() {
        println("getMilse  called")
        milse
    }

    private void setMilse(milse) {
        throw new IllegalAccessException("you're not allowed to change milse")
    }

    def drive(dist) {
        if (dist > 0) milse += dist
    }

}

def car = new Car2(2012)
println("year:$car.year")
println "milse: $car.milse"
println("Driving")
car.drive(10)
println("milse:$car.milse")

try {
    print "can i set the year?"
    car.year = 1900
} catch (ReadOnlyPropertyException ex) {
    println(ex.message)
}

try {
    print "can i set the milse?"
    car.milse = 12
} catch (IllegalAccessException ex) {
    println(ex.message)
}

从输出看到结果
year:2012
getMilse called
milse: 0
Driving
getMilse called
milse:10
can i set the year?Cannot set readonly property: year for class: groovy.Car2
can i set the milse?you’re not allowed to change milse

存取属性

//存取属性
Calendar.instance
//代替Calendar.getInsrance()
str="hello"
println str.class.name
//代替str.getClass().getName()
//注意:不能用map.builder等类型
//为保险起见,请使用str.getClass().name

灵活的初始化参数
groovy可以初始化一个javabean类,可以用逗号分隔赋值,也可以设计自己的方法,使其接受具名参数要利用这个特性,需要把第一个形参设置为map

package groovy

class Robot {
    def type, height, width

    def access(location, weight, fragile) {
        println "Received fragile? $fragile,weight:$weight,loc:$location"
    }
}

robot = new Robot(type: "arm", width: 10, height: 40)
println "$robot.type,$robot.height,$robot.width"

robot.access(x: 30, y: 20, z: 10, 50, true)
//可以修改参数程序
robot.access(50, true, x: 30, y: 20, z: 10)


`
运行一下,

arm,40,10
Received fragile? true,weight:50,loc:[x:30, y:20, z:10]
Received fragile? true,weight:50,loc:[x:30, y:20, z:10]
``
可选形参
groovy可以吧方法和构造器的形参设置为可选的,但是形参必须未与形参列表的末尾

package groovy

def log(x, base = 10) {
    Math.log(x) / Math.log(base)
}

println(log(1024))
println(log(1024, 10))
println(log(1024, 2))

打印一下

3.0102999566398116
3.0102999566398116
10.0
groovy还会吧末尾的数组形参视为可选的
所以在下面的例子中,可以为最后一个形参提供零个或多个值

def task(name,String[] details){
    println("$name -$details")
}
task("call","123-456-7890")
task("call","123-456-7890","231-546-0987")
task("call")

打印一下
call -[123-456-7890]
call -[123-456-7890, 231-546-0987]
call -[]

使用多赋值
从方法中返回多个结果,可能非常使用,要想从方法中返回多个结果,并将他们一次赋给多个变量,我们可以返回一个数组,然后将多个变量以逗号相隔,放在圆括号中,置于赋值表达式左侧即可,

def splitName(fullName){
    fullName.split(" ")
}
def (firstName,lastName)=splitName("james Bond")
println("$lastName,$firstName,$lastName")

打印一下,
Bond,james,Bond
可以看到,在将字符串切割后,返回的数组赋值个了两个对象,
还可以使用该特性来交换变量,无需创建中间变量来保存被交换的值,只需要将预交换的变量放在圆括号里,置于赋值表达式左侧,同时将他们以相反的顺序放在方括号里,置于右侧即可,

def name1="Thomson"
def name2="Thompson"
println("$name1 and $name2")
(name1,name2)=[name2,name1]
println("$name1 and $name2")

打印结果

Bond,james,Bond
Thomson and Thompson
Thompson and Thomson

切换完成,
在变量和值数量不匹配时,groovy也会处理,多余的的变量,会被设置为null,多余的值则会被丢弃

def (String cat,String mouse)=['tom','jerry','spike','tyke']
println("$cat and $mouse")

打印结果为:

tom and jerry
def(first,second,third)=['tom','jerry']
println("$first $second $third")

打印结果:

tom jerry null

但是这只是针对变量可以被设置为null的类型,在不能被设定为null的时候,groovy会抛出异常

Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'null' with class 'null' to class 'int'. Try 'java.lang.Integer' instead
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'null' with class 'null' to class 'int'. Try 'java.lang.Integer' instead
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

Process finished with exit code 1

布尔值
在java中,if判断必须要这样写

if(str != null){}

在groovy中,他会尝试判断,在布尔值的地方放置一个对象,他会检查该引用是否为null,他将null视作false,将非null视作true

String str="hello"
if (str) {print" hello"}

输出:


hello

操作符重载

for (ch = "a"; ch < "z"; ch++) {
    println(ch)
}

for (ch in "a".."g"){
    println(ch)
}

lst=["hello"]
lst<<"world"
println(lst)

使用’++’操作符来循环’a’—‘c’中的字符.这个’++’操作符映射到String类的next( ) 方法. 上面代码的输出:
++操作符实现了循环,使用的是string的next()的方法
<<操作符,向集合中添加元素,该操作符会被转换成groovy的collection添加的leftShift()方法

通过添加映射的方法,可以为自己的类提供操作符,比如为+添加plus()方法

package groovy

class CommplexNumber {
    def real, imaginary

    def plus(other) {
        new CommplexNumber(real: real + other.real,imaginary: imaginary + other.imaginary)
    }
    String toString() { "$real ${imaginary > 0 ? '+' : ''} ${imaginary}i" }
}

c1 = new CommplexNumber(real: 1, imaginary: 2)
c2 = new CommplexNumber(real: 4, imaginary: 1)
println c1 + c2

因为你ComplexNumber类中添加了plus( ) 方法,Groovy 允许你使用 + 获取两个复数相加 的结果 ,输出:5 + 3i
在某些方面操作符重载使表达式更具表现力. 不过, 通常情况下我并不喜欢操作符重载,因为 它很难被理解.

可变参数

等同于java 5中的变长参数。首先我们定义一个变长参数的方法sum:

int sum(int… var) {

def total = 0

for (i in var)

total += i

return total

}

我们可以在调用sum时使用任意个数的参数(1个,2个,3个……):

println sum(1)

println sum(1,2)

println sum(1,2,3)

def receiveVarArgs(int a, int ... b) {
    println("you passed $a and $b")
}

def receiveArray(int a, int[] b) {
    println("you passed $a and $b")
}
receiveVarArgs(1,2,3,4,5)
receiveArray(1,2,3,4,5)

打印结果:

you passed 1 and [2, 3, 4, 5]
you passed 1 and [2, 3, 4, 5]

注解
groovy支持所有java的注解,直接导入即可

静态导入

在java:
格式:import static 包名….类名.方法名;
可以直接导入到方法的级别
在groovy中,可以像java一样导入,可以为静态方法和类名定义别名,

import static Math.random as rand
import groovy.lang.ExpandoMetaClass as EMC


double value=rand()
def metaClass=new EMC(Integer)
assert metaClass.getClass().name=="groovy.lang.ExpandoMetaClass"

泛型
groovy支持泛型,但并不会提前检查,在运行中检查
在数据不符合泛型的时候,会尝试强制转型,如果失败,则抛出异常。

闭包和匿名内部类的冲突、
Groovyd 闭包是使用花括号的,而内部类也是使用的花括号,在正常情况下,可以通过把一个代码块附到函数调用末尾,将闭包传递给函数:instance.ethod(){}。按照这个习惯,我们可以向Calibrartor的构造器传递一个闭包来实例化一个实例,但在groovy中,错误的会认为要创建一个匿名内部类,

def calibrator3=new Calibrator(){
    println("123")
}

要绕开的话,就要修改调用方式,将闭包放在构造器调用语句的圆括号内。

def calibrator= new Calibrator({
    println("123")
})
def calculation={
    println("456")
}
def calibrator2=new Calibrator(calculation)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

离离原上草77

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值