Groovy语言语法基础
Groovy 语言学习个人Groovy目前学习所用主要是用于编写gradle插件。 Groovy安装下载GDKGDK,配置安装环境,也就是环境变量,跟java的类型(AS直接运行貌似可以不用),然后在Android Studio中开发Groovy,第一次运行的时候需要配置lib的路径,根据提示选择到groovy的安装目录下面的lib目录设置进去。这样子就可以了。 Groovy基本规则
只能在第一行的注释:#!
单行注释://
多行注释:/**/ 文档注释,也就是编译到doc里面的:/** */
as groovy.lang.*
groovy.util.*
java.lang.*
java.util.*
java.net.*
java.io.*
java.math.BigInteger
java.math.BigDecimal
使用到这些包的时候我们就不用去import了 Groovy语法基础HelloGroovy程序:我们首先在AS里面新建一个JAVA 程序或者是建立一个Android lib或者是app module,随便都行。然后新建一个名字随便的.groovy文件。比如mygroovy.groovy文件,文件的位置是位于src/main/java目录下面。 package com.example
public class HelloGroovy{
public static void main(String[] args) {
System.out.println("Hello Groovy")
}
}
然后对着代码右键,选择run,然后假如是第一次需要配置Groovy的jar进来。就选择你下载的Groov目录下面的lib目录配置进去,再次运行,就可以输出: Hello Groovy 这里的输出还是调用java的输出流实现的。 package com.example
System.out.println("Hello Groovy")
右键,run,还是输出Hello Groovy。这里的输出还是使用JAVA语言的输出流实现的。 package com.example
print("Hello Groovy")
print "Hello Groovy"
同样会都输出Hello Groovy,这里就是使用Groovy语言实现的。 定义变量我们可以使用java的强语言类型,使用各种不同的类型去定义变量,在这里不分享。Groovy还可以通过关键字def定义变量,他会根据上下文去推断这个变量的类型,需要强调一点,Groovy里面def声明一切都是对象。比如: package com.example
def a=10
def b=10L
def c="Hello Groovy"
def d=1.0
def e=1.0f
println(a.class)
println(b.class)
println(c.class)
println(d.class)
println(e.class)
输出: class java.lang.Integer
class java.lang.Long
class java.lang.String
class java.math.BigDecimal
class java.lang.Float
同时,在给一个变量赋值之后,也就是给定了类型之后,该变量还是可以指向别的类型的,比如: package com.example
def a=10;
println(a.class)
a = "Hello Groovy"
println(a.class)
输出就是: a=10;
println(a.class)
a = "Hello Groovy"
println(a.class)
但是,你以为就一定是需要def关键字吗,个人在AS里面测试运行的时候发现,我们可以把关键字def都省略掉,直接使用一个变量名字就可以,这就是动态语言的强大。变量堆指向的类型不关心,只要你给他什么类型,他就可以是什么类型。上面的例子是可以写成: package com.example
a=10;
println(a.class)
a = "Hello Groovy"
println(a.class)
这样子也是ok的。 类型兼容问题看下面一个例子: package com.example
char c = 'a'
println c.class
c='b'
println c.class
c2='a'
c3="a"
println c2.class
println c3.class
首先我们使用java的char关键字声明一个char 类型的变量c,然后打印类型,再次改变内容,再次打印类型,然后声明c2和c3,打印类型:输出结果是: class java.lang.Character
class java.lang.Character
class java.lang.String
class java.lang.String
可以看到,只要是使用java声明了类型,而后在后面改变了c的值,他的类型是没有改变的,但是直接声明c2和c3,无论使用”还是”“,类型都是String。所以我们得知,在Groovy直接声明变量中是只能变为String,而不能变为Character。除非你是强制类型装换或者是使用as char,比如: package com.example
c = (char) "c"
c2 = "c" as char
这样子就可以装换为Character。 package com.example
char c = 'a'
println(c.class)
c="aa"
println(c.class)
就会报 Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'aa' with class 'java.lang.String' to class 'char'
但是假如你是把c指向int,float,double,只要是没有超出char的范围,或者是只有一个字符的字符串,比如“A”,而且他是可以使用Character.valueOf()方法转化的,那么它也会被赋值成功。 as 保留字 Groovy的字符串GString
package com.example
str = "hello"
str1 = 'hi${str}'
str2 = "hi${str}"
str3 = "${str}hi"
println(str1)
println(str2)
println(str3)
a = 1;
b = 2;
输出: hi$str
hihello
hellohi
sum = 3
sum2 = 3
可以看到使用单引号插值占位符不起效。 ${var}
当$位于语句末端的时候,{}可以省略,其他的一般不要省略,比如上面的str的就可以省略,但是str3的省略就会出错。我们可以用它来插入变量。有点类似JAVA的String的Format。 sum="sum = ${a + b}"
sum2 ="sum2 = ${1 + 2}"
println(sum)
println(sum2)
输出: sum = 3
sum2 = 3
占位符中调用方法 a = 1;
sum="sum = ${a.hashCode()+getInt() }"
sum2 ="sum2 = ${getInt()}"
println(sum)
println(sum2)
private int getInt() {
return 3;
}
package com.example
str='''hello Groovy'''
println(str)
就可以输出hello Groovy。三重引用字符不支持插值占位符的操作,比如: str = "Groovy"
str1='''hello${str}'''
str1的结果是hello${str},不会是hello Groovy。 str1='''hello Groovy'''
println(str1)
println(str1.contains("n"))
打印输出的就是: hello
Groovy
true
换行符会被替换成”n”。其他的留白会照常输出。使用””表示不转义,它本身是支持转义的,比如: str1=''' HellotGroovy'''
println(str1)
println(str1.startsWith("n"))
输出结果: Hello Groovy
false
可以看到换行符没有使用转义,也就没有输出一个换行了。使用t就是一个tab键距离。 c = "hello"
str=" n ${c}+tGroovy"
println(str)
输出: hello+ Groovy 可以看到他跟单引号的区别是可以使用占位符。其他的类似。 s="Groovy"
str=/Hello ${s}/ as String
str1 = "Hello Groovy" as String
println(str.equals(str1))
输出就是true。同样支持多行和占位符。 Groovy的运算符Groovy支持Java所有的运算符,但是它本身还支持另外一些运算符 String str;
str2 =str?.hashCode()
println(str2)
这里是照常输出不会出现空指针,使用?的意思就是它不为空的时候调用对应的属性的方法。使用“.”调用方法或者改属性对应的属性。 2**3 结果就是8,就是2的三次方的意思 str = "Hello Groovy" as Strin
//常规写法
str2 = str == null ? "Hello Java" : str
//Groovy写法
str3 = str?str:"Hello Java"
// 简化写法
str4=str?:"Hello Java"
其中第一种写法是比较明了的,第二种写法的意思是:当str不为空的时候,调用前者,为空的时候,调用后者,第三种写法的意思是,当str不为空的时候,使用自己,为空的时候使用后者。 还有一部分的运算符,可以参考Operators Groovy 导入别的类语法是跟java一样,使用import关键字,比如: import groovy.xml.MarkupBuilder
import static Boolean.FALSE // 静态导入,可以直接使用它的一些静态变量和方法而不用使用类.方法调用。
import static java.lang.Boolean.FALSE as f// 取别名,可以想下面那样子去使用FALSE。
f a = false
循环switch/case结构例子: def x =1.2
def result = ""
switch ( x ) {
case "foo":
result = "found foo" // lets fall through
case "bar":
result += "bar"
break
case [4,5,6,'inList']:
result = "list"
break
case 12..30:
result = "range"
break
case Integer:
result = "integer"
break
case Number.class:
result = "number"
break
case ~/fo*/: // toString() representation of x matches the pattern?
result = "foo regex"
break
case { it < 0 }: // or { x < 0 }
result = "negative"
break
default:
result = "default"
}
println(result
可以看到,在switch case结构体中,他是支持很多种类型的匹配的,可以是正则匹配,可以是类匹配,可以是字符串,数字匹配,也可以是表达式的匹配,按照从上到下的方式进行匹配,这里的输出是Number。 for循环支持经典的for循环,例子这里也就不写了。还有别的循环。 int sum;
for (i in 1..9) {
sum+=i
}
println(sum)
注意的是这里的i是没有指定类型的,直接是i in num,就是i在某个范围内循环,输出的是45. arr = [1,2,3,4] as int[]
sum = 0 as int
for (i in arr) {
sum+=i;
}
println(sum)
就是输出10 //从2到5循环,包括3
2.upto(5,{ print(it) })
println()
//从0开始循环2次,每次加1
2.times { print(it) }
println()
//从2开始,每次加2,输出小于10的值
2.step(10,2,{print(it)})
输出: 2345 01 2468 数据结构Listlist = [1,"2",false];
println(list.getClass())
list.add(3)
list.add(0,"4")
list.addAll([5,7,1])
println(list)
list.remove(false)
println(list)
println(list.indexOf(1))
输出: class java.util.ArrayList
[4,1,false,1]
[4,1]
1
支持增删查改,默认的类型是ArrayList,在初始化的时候可以进行赋值。可以通过as操作符强转。比如 list = ["A","B","C"] as LinkedList<String>
Groovy还支持多维的List,比如: list = [[1,2],[3,4]];
sum = 0
for (i in list) {
for (j in i) {
sum+=j
}
}
println(sum)
就会输出10,有点类型多维数组。 Mapmap = [A: 1,B: 2,C: 3] as Map<String,Integer>
for (i in map) {
println("Key="+i.getKey()+",value="+i.getValue())
}
map.put("D", 4)
map.remove("A")
println(map)
i = map.get("C")
println(i)
输出是: Key=A,value=1
Key=B,value=2
Key=C,value=3
[B:2,C:3,D:4]
3
map同样支持初始化的时候进行赋值,他的赋值是,[key:value…],支持Java的map的所以操作。当我们没有为map指定类型的时候,他会根据上下文去推断map 的类型。 数组数组的定义跟JAVA的类似,比如 arr = [1,4,5] as int[]
String[] arr2 = ["A","C"]
sum = 0;
for (i in arr) {
sum+=i;
}
String str="";
for (i in arr2) {
str+=i
}
println(sum)
println(str)
输出了: 15
[A,B,C]
这里需要注意的是定义数组的时候不要跟定义List混淆,arr = [1,3,4,5]是定义为一个List。arr[]=[1,5]是一种错误的定义方法。 Groovy封装定义定义类首先基本的类型有: package com.example.bean
class Person{
String name;
Integer age;
@Override
String toString() {
return "Name=${name},age=${age}"
}
然后在上一级的包中去测试: package com.example
import com.example.bean.Person
def person = new Person()
person.age = 30;
person.name="Hello"
println(person)
发现正常打印结果。同时我们可以通过他默认提供的get/set方法设置属性值。但是有一点我们需要注意,假如有时候我们自己定义了get和set方法,这里面的get和set方法跟默认生成的不一样。假如是直接调用get好set的时候就会调用我们自己生成的,但是假如我们需要调用系统生成的时候,就可以使用域访问符”.@”了,例子如下: // Person的getName()方法
public String getName() {
return "java"
}
//使用比较
Person p1 = new Person(name: "Groovy",age: 30)
println(p1.getName())
println(p1.@name)
这样子就可以使用系统为我们生成的get/set方法了。 public Person(name,age) {
this.name = name;
this.age = age;
}
然后在使用它,可以跟JAVA一样子使用,也可以是下面那样子使用,比如: // java使用
person = new Person("Hello",12)
println(person)
//Groovy多出的方式
Person p = ["Groovy",20]
println(p)
参数列表需要跟构造参数的参数列表相对应。 Person p1 = new Person(name: "java",age: 30)
Person p2 = new Person(age: 40,name:"PHP")
Person p3 = new Person(name: "hei")
Person p4 = new Person(age:10)
使用这种构造器的时候,我们的类需要没有构造器或者是构造器是空构造器的时候就可以使用。所以,我们一般使用Groovy的时候,假如没有特殊的要求,尽量可以不提供有参数的构造器,以为Groovy会提供足够的构造器给我们使用。 定义方法例子如下: def someMethod() { 'method called' }
String anotherMethod() { 'another method called' }
def thirdMethod(param1) { "$param1 passed" }
static String fourthMethod(String param1) { "$param1 passed" }
1.不用声明返回类型,而,输入参数可以不指定类型。这是Groovy比较特别的。例如我们在上面的Person类添加一下方法如下: def getJob() {
return "Groovy devr"
}
def setJob(job) {
return "Good ${job}"
}
由于没有设置限定修饰符,所以都是public的。 import com.example.bean.Person
Person p1 = new Person(name: "java",age: 30)
println(p1.getJob())
println(p1.setJob("HeiHeiHei"))
这样子就可以输出: Groovy devr Good HeiHeiHei 定义属性一般定义属性跟java类型,可以有修饰符,没有修饰符则是public的。 闭包终于学习到我们的重点了,闭包。 package com.example.closure
public interface MyClosure{
void accept(String A)
}
然后使用它: MyClosure p = { println(it.contains ('G') )}
p.accept("Groovy")
结果会输出true。这就是一个闭包。闭包的定义; { [closureParameters -> ] statements }
说明: // 简单的闭包
{ item++ }
// 使用->分离参数和语句
{ -> item++ }
//闭包使用隐式参数
{ println it }
// 闭包使用显示参数
{ it -> println it }
// 这种情况最好指定参数
{ name -> println name }
//接收两个参数,并且答应对应的值
{ String x,int y ->
println "hey ${x} the value is ${y}"
}
//闭包可以包含多个语句,同时可以使用{}包裹起来,也可以不用。
{ reader ->
def line = reader.readLine()
line.trim()
}
以上例子是来自Groovy官网的例子。 def listener = { e -> println "Clicked on $e.source" }
println listener instanceof Closure
Closure callback = { println 'Done!' }
Closure<Boolean> isTextFile = {
File it -> it.name.endsWith('.txt')
}
输出的是: true
def code= { 123 }
println(code() == 123) println(code.call()==123)
这里定义了一个闭包code,直接调用code()或者是直接调用code.call()方法。当闭包有参数的时候,比如: def code={s->"Hello ${s}"}
println(code("Groovy")) println(code.call("Java"))
我们会在闭包调用或者call调用中传入参数,这样子就可以了。 // 只有一个参数,没有指定类型,返回值是String
def closureWithOneArg = { str -> str.toUpperCase() }
assert closureWithOneArg('groovy') == 'GROOVY'
//指定类型,只有一个参数,返回值是String
def closureWithOneArgAndExplicitType = { String str -> str.toUpperCase() }
assert closureWithOneArgAndExplicitType('groovy') == 'GROOVY'
//多个参数,返回值是int或者是String或者是其他可以执行+运算符的对象
def closureWithTwoArgs = { a,b -> a+b }
assert closureWithTwoArgs(1,2) == 3
//指定类型,返回值是int
def closureWithTwoArgsAndExplicitTypes = { int a,int b -> a+b }
assert closureWithTwoArgsAndExplicitTypes(1,2) == 3
//指定其中一个类型,a的类型需要能够与b进行+运算符操作
def closureWithTwoArgsAndOptionalTypes = { a,int b -> a+b }
assert closureWithTwoArgsAndOptionalTypes(1,2) == 3
//指定一个默认值b为2
def closureWithTwoArgAndDefaultValue = { int a,int b=2 -> a+b }
assert closureWithTwoArgAndDefaultValue(1) == 3
// 默认有一个参数
def code={"Hello ${it}"}
println(code.call("Groovy"))
//跟上面的作用一样
code={it->"Hello ${it}"}
println(code.call("PHP"))
//没有任何的参数
code= { -> "Hello Java" }
println(code.call())
输出: Hello Groovy Hello PHP Hello Java
def code={a,String... arg->
println(a)
println(arg[0])
println(arg[1])
}
code.call(1,"A","B")
就会输出1,A,B def code= { a,b -> println(a + b) }
def methodClosure(a,b,Closure c){
c.call(a,b)
} //第一种调用
methodClosure(1,code) // 第二种调用
methodClosure(1,{ a,b -> println(a + b) }) // 第三种调用
methodClosure(1,2) {
a,b ->
println(a + b)
}
输出: 2345 3 3 3 Groovy 学习推荐 Documentation (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |