Groovy基础学习
首先,了解一下什么是Groovy:
·它是一种像Java一样运行在JVM上,但更加敏捷的动态语言。
·它的语法理念源于Python,Ruby和Smalltalk,但它的语法与Java语言的语法很是相似。
·相比于Java,大大减少了代码量,让人更加容易阅读和维护,提高了开发效率
·Groovy无缝的集成了Java现有的所有的类和库,直接编译成Java字节码,因此可以和Java很好的结合利用。
·简化了测试,支持单元测试,具有开箱即用的功能。
有Java基础的,对于学习Groovy是没有任何障碍的,需要在实际应用中,不断融入自己的代码中,提高效率。
接下学习Groovy
最简单的例子来看看Groovy语法的简练(对比Java)
在Java中,输出“hello world”代码如下:
public class HelloWorld {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("hello world ");
}
}
结果:hello world
而用Groovy,输出“hello world”代码如下:
println "hello world"
结果:hello world
若是仅需要达到输出功能,则不需要定义类和main方法,只需一句输出语句,也不需要System.out和括号,就可以达到同样的效果,是不是相当简练!
接下来详细看一下Groovy的一些语法特点:
1.在声明一个变量时,groovy *不要求强制类型声明* ,仅仅要求变量名前使用关键字def(在方法参数和循环声明中不需要) 如下:
class Test1 {
static main(args) {
def var1 = "hello"
def var2 = 123
def var3 = true
println var1
println var1.class
println var2
println var2.class
println var3
println var3.class
}
}
结果:
hello
class java.lang.String
123
class java.lang.Integer
true
class java.lang.Boolean
可以看出,虽然没有声明变量类型,但是Groovy还是可以自动的识别变量的类型,这是因为在Groovy中,所都的变量都被当做对象对待,举个例子:将上面main中的代码修改如下
def var1 = "hello"
println var1
println var1.class
var1 = 123
println var1
println var1.class
结果为:
hello
class java.lang.String
123
class java.lang.Integer
说明,同一个变量,在运行中赋予不同的类型,则它就会动态的改变,即它一直以对象的状态存在,随时可以发生变化。
2. Groovy中默认的修饰符为public,因此在main方法面不需要public修饰,在上面的例子中,并没有写public,效果还是一样的。
3. 每句代码后面“;”是可选的,如果同一行有俩句语句,则用“;”分割,否则并不需要,上面的代码中可以看出,只需换行就ok了。
4. 用Groovy写循环语句时,也会简单很多,同一个循环语句,用Java编写如下:
public class SayHello {
public static void main(String[] args) {
for(int i=0;i<5;i++){
System.out.println("hello");
}
}
}
结果:
hello
hello
hello
hello
hello
而用Groovy代码如下:
def repeat(){
for(i=0;i<5;i++){
println "hello"
}
}
repeat()
结果:
hello
hello
hello
hello
hello
对比一下发现,在Groovy循环中,不需要在循环变量前加def,也不需要对 i 指定数据类型 int
把循环继续修改为如下:
for(i in 0..4){
println "hello"
}
结果:
hello
hello
hello
hello
hello
效果是一样的,但是显得更加简练。这里的 0..4 涉及到了关于Groovy中的范围的概念:
范围是一系列的值,如0..4代表0 1 2 3 4 ,a..d代表a b c d,于此同时,它也支持排除范围,如0..<4表示0 1 2 3 即不包含4,a..
def repeat(val,repeat=5){
for(i in 0..<repeat){
println val
}
}
repeat("hello",2)
repeat("world",3)
repeat("repeat")
结果:
hello
hello
world
world
world
repeat
repeat
repeat
repeat
repeat
可以看出,若不指定循环次数,则会调用默认值,即输出5次“repeat”。
5.关于Groovy中的集合,这是Groovy相比较于Java很是突出的一部分,它能够很方便的操作集合。因为在Groovy中,集合是以内置的方式存在,不需要像在Java中一样,导入专门的类然后初始化,而是可以直接进行定义以及对数据的添加删除等操作。看一个例子:使用Java,对一个集合进行操作,如下:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Filter {
public static void main(String[] args) {
List list = new ArrayList();
list.add("Rod");
list.add("Neeta");
list.add("Eric");
list.add("Missy");
Filter filter = new Filter();
List shorts = filter.filterLongerThan(list, 4);
System.out.println(shorts.size());
Iterator iter = shorts.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
}
public List filterLongerThan(List list, int length) {
List result = new ArrayList();
Iterator iter = list.iterator();
while (iter.hasNext()) {
String item = (String) iter.next();
if (item.length() <= length) {
result.add(item);
}
}
return result;
}
}
结果:
2
Rod
Eric
而使用Groovy,代码如下:
def list = ["Rod", "Neeta", "Eric", "Missy"]//定义一个集合并将数据放入集合中
def shorts = list.findAll { it.size() <= 4 }//定义一个集合,并对集合直接进行操作
println shorts.size()//输出所需要的结果
shorts.each { println it }//遍历集合
结果:
2
Rod
Eric
对比可以看出,在Java中,需要导入专门的类,需要进行初始化,需要使用add()方法进行对数据的添加,在取出数据时,还需用到迭代器取出,而使用Groovy的时候,可以直接定义一个集合,将数据直接放入其中。
在对数据进行操作时,可以用到一下方法:
例如给上面的list中添加数据,
def list = ["Rod", "Neeta", "Eric", "Missy"]//定义一个集合并将数据放入集合中
list.add("Harry")//add()方法
list<<"hey"//操作符重载方式添加
list[6] = 'Ide'//根据位置来添加,注意如果覆盖了原有位置,则会覆盖对应的数据
结果:
[Rod, Neeta, Eric, Missy, Harry, hey, Ide]
检索某一项数据:
assert list[1] == "Neeta"//检测正确性,若正确,则程序继续运行,否则将中断并报详细错误
结果:
[Rod, Neeta, Eric, Missy, Harry, hey, Ide]//说明上面取出的数据是正确的
这是一个错误的例子:
def list2 = [1,2,3]
assert list2[1] == 1//the right is 2
println list2
结果:
Caught: Assertion failed:
assert list2[1] == 1
| | |
| 2 false
[1, 2, 3]
细心一点还会发现一个问题:在上面的代码assert list[1] == "Neeta"
中,对于String类型的判断,用的居然是“==”,而且还是正确的结果,这里,其实还是Groovy中的关于一切变量都是对象的实现,表面上看是“==”,但在底层实际上已经重现了这个方法,用的还是equals方法。
6.关于Groovy中的映射,Java 语言中的映射是名称-值对的集合。所以,要用 Java 代码创建典型的映射,必须像下面这样操作:
Map<String,String> map = new HashMap<String,String>();
map.put("key1","hello");
map.put("key2","world");
而使用Groovy处理映射的操作如下:
def map = [key1:"hello",key2:"world"]
当我们需要对集合进行迭代时,可以用如下方法:
map.each {
println it
}
结果:
key1=hello
key2=world
这里涉及到关于Groovy中的闭包,它的形式为:“{”代码“}”,即一个大括号,中间加代码。在上面的each后的内容,即为一个闭包的形式,”it”是一个关键字,它指向被调用集合外部的每个值,它是一个默认值。我们可以改变它:
def map = [key1:"hello",key2:"world"]
map.each { values-> //将默认it用values替代
println values
}
结果:
key1=hello
key2=world
以上是对默认参数和一个参数的迭代,再来看一下多个参数的的迭代:
def map = [key1:"hello",key2:"world"]
map.each {key,values-> //俩个参数
println "${key},${values}"
}
结果:
key1,hello
key2,world
可以看出,使用“${参数…}”的方式,可以对多个参数进行迭代。
在上面的代码中,还有一点值得注意,在输出语句中,如果将println "${key},${values}"
中的双引号改为单引号,结果如下:
${key},${values}
${key},${values}
这里可以说明,在虽然单引号和双引号在输出一句话的时候可以随便使用,但涉及到调用表达式的时候,则必须使用双引号。
7.关于Groovy中的类定义和Java的基本相似,它的方法可以基于类(static)或者实类,可以为public,protect,private,支持常用的Java修饰符,比如synchronized,但它的缺省是public,所以我们在定义时,并不需要写public,它的方法的参数的类型不是强制性的,这点和Java不同。先看一个最简单的类的定义:
class Employee {
def id
def name
def salary
def display(){
println "ID:${id},Name:${name},Salary:${salary}"
}
}
创建对象并调用方法:
def employees = new Employee(id:1,name:'jor',salary:1000)
employees.display()
结果:
ID:1,Name:jor,Salary:1000
如果是这样进行创建实类对象:
def employees = new Employee()
employees.display()
同样可以通过,结果为:
ID:null,Name:null,Salary:null
可以看出,在上面的类中并没有定义它的构造方法,相当于Groovy提供了默认的构造方法,所以在创建对象时,即使是空的对象参数,依旧可以创建,其值为null,当然也可以显式的定义构造方法:
class Employee {
def id
def name
def salary
def Employee(id,name,salary){
this.id = id
this.name = name
this.salary = salary
}
def display(){
println "ID:${id},Name:${name},Salary:${salary}"
}
}
创建实类:
def employees = new Employee(1,'jor',1000)
employees.display()
结果:
ID:1,Name:jor,Salary:1000
如果按上面的第二种方式继续创建一个实类:
def employees = new Employee()
则会报错
def employees = new Employee(id:1,name:'jor',salary:1000)
这样的方式来创建对象更加灵活,这时不需要自定义构造方法。
将上面的类修改如下:
class Employee {
def id
def name
def salary
String toString(){
return "${id},${name},${salary}"
}
}
结合集合同时创建多个对象:
def employees = [
new Employee(id:1,name:'hell',salary:5000),
new Employee(id:2,name:'sili',salary:4000),
new Employee(id:3,name:'mald',salary:7000)]
employees.each{employee->println employee}
结果:
1,hell,5000
2,sili,4000
3,mald,7000
这里利用重写 toString 方法结合前面的集合及闭包,很容易实现对多个对象的创建及输出。
8.关于Groovy中的安全导航操作符:(?.),当程序进行判断操作的时候,可以很好的减少条件语句,例如:
def foo(str)
{
if(str!=null) {return str.reverse()}
}
println foo("hello")
结果:
olleh
替换后如下:
def foo(str)
{
str?.reverse()
}
println foo("hello")
结果:
olleh
9.关于Groovy的结构,和Java中基本类似,包含判断语句if..else,switch,三元操作符,循环语句for,while,(do…while不支持),以及continue和break给个例子:
def val = 'a';
while(val++<'e'){
if(val=='b'){
println val
}else{
println val+'s'}
}
结果:
b
cs
ds
es
switch语句在Groovy中比较强大,它可以匹配任何类型的值,例如:
v = 2
switch(v){
case Number:println "choosed number";
case ~"\\.+\\.":println "choosed matchRegex";
case [1,1,1,1] :println "choosed List";
}
结果:
choosed number
choosed matchRegex
choosed List
解释一下,本来应该每句的末尾加break的,但为了验证它的功能,将后面的也都执行了一次。
10.关于Groovy中的Boolean,它和Java中的Boolean类型的用法还是有很大的区别,例如,在Java中:
int val = 1;
if(val){
System.out.println("true");
}
结果错误的,因为if中必须得判断表达式才可以
而在Groovy中,
def val = 1
if (val){
println "true"
}
结果:
true
说明将一个对象放在一个boolean表达式中,Groovy会自动检测这个对象是否为null,如果为null,则返回false,否则为true。下面列出了在不同的类型中Boolean值的判定规则:
类型 | 为true的条件 |
---|---|
Boolean | true |
Collection | 不为空 |
Character | 值不为 0 |
CharSequence | 长度> 0 |
Enumeration | 有更多元素 |
Iterator | 有文件 |
Number | 双精度值不为0 |
Map | 不为空 |
Matcher | 至少一个匹配 |
Object[ ] | 长度> 0 |
任何其他类型 | 引用不为 null |
11.关于Groovy中简单的文件操作:
读取指定文件内容:
File file = new File('E:/test1.txt')
file.eachLine {lines->
println lines }
结果:
hello
world
haha
按指定格式读取:
file.eachLine("utf8") {println it }
向文件中写入内容:
file.append('0.0.0.0.')
file.eachLine {println it }
结果:
hello,harry,dd,dd,f,g,h
world is beautiful,isn't it?
byby
0.0.0.0.
直接就可以操作,用不着关心关于流,异常控制,资源关闭等操作,Groovy搞定了这些,是很简练吧。
12.关于Groovy中简单的正则表达式应用:
def str='abcdefg'
assert str=~'abc'
运行正确,说明在用“=~”只要字符串是被匹配字符串的子串,表达式就是正确的。
----------
def str='abcdefg'
assert str==~'abc'
结果:
Caught: Assertion failed:
assert str==~'abc'
| |
| false
abcdefg
说明“==~”为精确匹配,只有完全相同时,才正确。
13.关于Groovy中的单元测试:
首先将JUnit导入Eclipse项目中:
选择JUnit4,完成后项目下会出现包:
然后新建一个测试类:选择你要测试的项目–>new一个JUnit test case–>填写测试类名,包名及所要测试的类–>完成,编写测试方法进行测试。