大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。
Groovy新手教程
一、groovy是什么
简单地说,Groovy 是下一代的java语言,跟java一样,它也执行在 JVM 中。
作为跑在JVM中的还有一种语言,groovy语法与 Java 语言的语法非常类似。同一时候,Groovy 抛弃了java烦琐的文法。相同的语句,使用groovy能在最大限度上降低你的击键次数——这确实是“懒惰程序猿们”的福音。
二、开发环境
1、 jdk 1.5以上
2、 eclipse groovy plugin(支持Groovy 1.5.7)
打开eclipse,通过Software Updates > Find and Install…菜单,使用“Search for new features to install” 下载并安装groovy插件。New一个远程网站,url可使用http://dist.codehaus.org/groovy/distributions/update/,插件名:Groovy plug-in。依据须要你能够同一时候选择groovy和grails(兴许会学习到):
三、创建groovy项目
1、 新建一个groovy项目
New –> Project à Java Project 创建一个java项目。为了方便管理,建议在source中建两个source目录java和groovy,分别用于存储java源文件和groovy源文件:
2、 加入� Groovy 特性
在项目上右击,Groovy à Add Groovy Nature,这样会在项目中加入� Groovy Libraries。
3、 加入� Groovy 类
在项目groovy源文件下右键,New à Other àGroovy à Groovy Class
自己主动生成的源码例如以下:
public class HelloWorld{
/**
* @param args
*/
public static void main(def args){
// TODO Auto-generated method stub
}
}
我们在main方法中加一句打印语句:
println “Hello World”
4、 编译执行groovy类
在源文件上右键,Compile Groovy File,然后右键,Run As à Groovy ,在控制台中查看执行结果。
实际上 groovy 语法的简练还体如今,就算整个文件里仅仅有println “Hello World”这一句代码(把除这一句以外的语句删除掉吧),程序也照样可以执行。
当然,为了说明groovy 事实上就是java,你也能够全然依照java 语法来编写HelloWorld类。
四、Groovy语法简单介绍
1、 没有类型的java
作为动态语言,groovy中全部的变量都是对象(相似于.net framework,全部对象继承自java.lang.Object),在声明一个变量时,groovy不要求强制类型声明,只要求变量名前使用keyworddef(从groovy jsr 1開始,在曾经的版本号中,甚至连def都不须要)。
改动main 方法中的代码:
def var=“hello world”
println var
println var.class
你能够看到程序最后输出了var的实际类型为:java.lang.String
作为例外,方法參数和循环变量的声明不须要def。
2、 不须要的public
你能够把main方法前面的public去掉,实际上,groovy中默认的修饰符就是public,所以public修饰符你根本就不须要写,这点跟java不一样。
3、 不须要的语句结束符
Groovy中没有语句结束符,当然为了与java保持一致性,你也能够使用;号作为语句结束符。在前面的每一句代码后面加上;号结束,程序相同正常执行(为了接受java程序猿的顽固习惯)。
4、 字符串连接符
跟java一样,假设你须要把一个字符串写在多行里,能够使用 号连接字符串。代码能够这样写:
def var=“hello “
“world”
“,groovy!”
当然更groovy的写法是:
def var=“””hello
world
groovy!“””
三个”号之间不在须要 号进行连接(只是字符串中的格式符都会被保留,包含回车和tab)。
5、 一切皆对象
听起来象是“众生平等”的味道,其实groovy对于对象是什么类型并不关心,一个变量的类型在执行中随时能够改变,一切依据须要而定。假设你赋给它boolean ,那么无论它原来是什么类型,它接受boolean值之后就会自己主动把类型转变为boolean值。看以下的代码:
def var=“hello “
“world”
“,groovy!”
println var;
println var.class;
var=1001
println var.class
输出结果:
hello world,groovy!
class java.lang.String
class java.lang.Integer
var这个变量在程序执行中,类型在改变。一開始给它赋值String,它的类型就是String,后面给它赋值Integer,它又转变为Integer。
6、 循环
删除整个源文件内容,用下面代码替代:
def var=“hello “
“world”
“,groovy!”
def repeat(val){
for(i = 0; i < 5; i ){
println val
}
}
repeat(var)
输出:
hello world,groovy!
hello world,groovy!
hello world,groovy!
hello world,groovy!
hello world,groovy!
注意循环变量i前面没有def。当然也没有java中常见的int,但假设你非要加上int也不会有错,由于从Groovy1.1beta2之后開始(不包含1.1beta2),groovy開始支持java经典的for循环写法。
此外,上面的for语句还能够写成:
for(i in 0..5)
这种结果是一样的。
7、 String 和 Gstring
除了标准的java.lang.String以外(用’号括住),groovy还支持Gstring字符串类型(用“号括住)。把上面的for循环中的语句改成:
println “This is ${i}:${val}”
执行一下,你就会明确什么是Gstring。
8、 范围
这个跟pascal中的“子界”是一样的。在前面的for循环介绍中我们已经使用过的for(i in 0..5)这种使用方法,当中的0..5就是一个范围。
范围 是一系列的值。比如 “0..4” 表明包括 整数 0、1、2、3、4。Groovy 还支持排除范围,“0..<4” 表示 0、1、2、3。还能够创建字符范围:“a..e” 相当于 a、b、c、d、e。“a..<e” 包括小于 e 的全部值。
范围主要在for循环中使用。
9、 默认參数值
能够为方法指定默认參数值。我们改动repeat方法的定义:
def repeat(val,repeat=3){
for(i in 0..<repeat){
println “This is ${i}:${val}”
}
}
能够看到,repeat方法添加�了一个參数repeat(而且给了一个默认值3),用于指定循环次数。
当我们不指定第2个參数调用repeat方法时,repeat參数取默认值3。
10、 集合
Groovy支持最常见的两个java集合:java.util.Collection和java.util.Map。前面所说的范围实际也是集合的一种(java.util.List)。
(1) Collection
Groovy 中这样来定义一个Collection:
def collect=[“a”,“b”,“c”]
除了声明时往集合中加入�元素外,还能够用下面方式向集合中加入�元素:
collect.add(1);
collect<<“come on”;
collect[collect.size()]=100.0
Collection使用相似数组下标的方式进行检索:
println collect[collect.size()-1]
println collect[5]
groovy支持负索引:
println collect[-1] //索引其倒数第1个元素
println collect[-2] //索引其倒数第2个元素
Collection支持集合运算:
collect=collect 5 //在集合中加入�元素5
println collect[collect.size()-1]
collect=collect–‘a’ //在集合中减去元素a(第1个)
println collect[0] //如今第1个元素变成b了
相同地,你能够往集合中加入�还有一个集合或删除一个集合:
collect=collect–collect[0..4] //把集合中的前5个元素去掉
println collect[0] //如今集合中仅有一个元素,即原来的最后一个元素
println collect[-1] //也能够用负索引,证明最后一个元素就是第一个元素
(2) Map
Map是“键–值”对的集合,在groovy中,键不一定是String,能够是不论什么对象(实际上Groovy中的Map就是java.util.Linke dHashMap
)。
如此能够定义一个Map:
def map=[‘name’:‘john’,‘age’:14,‘sex’:‘boy’]
加入�项:
map=map [‘weight’:25] //加入�john的体重
map.put(‘length’,1.27) //加入�john的身高
map.father=‘Keller’ //加入�john的父亲
能够用两种方式检索值:
println map[‘father’] //通过key作为下标索引
println map.length //通过key作为成员名索引
11、 闭包(Closure)
闭包是用{符号括起来的代码块,它能够被单独执行或调用,也能够被命名。相似‘匿名类’或内联函数的概念。
闭包中最常见的应用是对集合进行迭代,以下定义了3个闭包对map进行了迭代:
map.each({key,value-> //key,value两个參数用于接受每一个元素的键/值
println “$key:$value”})
map.each{println it} //it是一个keyword,代表map集合的每一个元素
map.each({ println it.getKey() “–>” it.getValue()})
除了用于迭代之外,闭包也能够单独定义:
def say={word->
println “Hi,$word!”
}
调用:
say(‘groovy’)
say.call(‘groovy&grails’)
输出:
Hi,groovy!
Hi,groovy&grails!
看起来,闭包相似于方法,须要定义參数和要运行的语句,它也能够通过名称被调用。然而闭包对象(不要奇怪,闭包也是对象)能够作为參数传递(比方前面的闭包作为參数传递给了map的each方法)。而在java中,要做到这一点并不easy(或许C 中的函数指针能够,但不要忘记java中没有指针)。其次,闭包也能够不命名(当然作为代价,仅仅能在定义闭包时运行一次),而方法不能够。
12、 类
Groovy类和java类一样,你全然能够用标准java bean的语法定义一个groovy 类。但作为还有一种语言,我们能够使用更groovy的方式定义和使用类,这种优点是,你能够少写一半以上的javabean代码:
(1) 不须要public修饰符
如前面所言,groovy的默认訪问修饰符就是public,假设你的groovy类成员须要public修饰,则你根本不用写它。
(2) 不须要类型说明
相同前面也说过,groovy也不关心变量和方法參数的详细类型。
(3) 不须要getter/setter方法
不要奇怪,在非常多ide(如eclipse)早就能够为序员自己主动产生getter/setter方法了。在groovy中,则彻底不须要getter/setter方法——全部类成员(假设是默认的public)根本不用通过getter/setter方法引用它们(当然,假设你一定要通过get/set方法訪问成员属性,groovy也提供了它们)。
(4) 不须要构造函数
不在须要程序猿声明不论什么构造函数,由于groovy自己主动提供了足够你使用的构造函数。不用操心构造函数不够多,由于实际上仅仅须要两个构造函数(1个不带參数的默认构造函数,1个仅仅带一个map參数的构造函数—由于是map类型,通过这个參数你能够在构造对象时随意初始化它的成员变量)。
(5) 不须要return
Groovy中,方法不须要return来返回值吗?这个似乎非常难理解。看后面的代码吧。
因此,groovy风格的类是这种:
(6) 不须要()号
Groovy中方法调用能够省略()号(构造函数除外),也就是说以下两句是等同的:
代码语言:javascript复制person1.setName 'kk'
代码语言:javascript复制person1.setName('kk')
以下看一个完整类定义的样例:
class Person {
def name
def age
String toString(){//注意方法的类型String,由于我们要覆盖的方法为String类型
“$name,$age”
}
假设你使用javabean风格来做相同的事,起码代码量要添加�1倍以上。
我们能够使用默认构造方法实例化Person类:
def person1=new Person()
person1.name=‘kk’
person1.age=20
println person1
也能够用groovy的风格做相同的事:
def person2=new Person([‘name’:‘gg’,‘age’:22]) //[]号能够省略
println person2
这样须要注意我们覆盖了Object的toString方法,由于我们想通过println person1这个方案简单地打印对象的属性值。
然而toString 方法中并没有return 一个String,但不用操心,Groovy 默认返回方法的最后一行的值。
13、 ?运算符
在java中,有时候为了避免出现空指针异常,我们通常须要这种技巧:
if(rs!=null){
rs.next()
… …
}
在groovy中,能够使用?操作符达到相同的目的:
rs?.next()
?在这里是一个条件运算符,假设?前面的对象非null,运行后面的方法,否则什么也不做。
14、 可变參数
等同于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)
15、 枚举
定义一个enum:
enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
然后我们在switch语句中使用他:
def today = Day.SATURDAY
switch (today) {
//Saturday or Sunday
case [Day.SATURDAY, Day.SUNDAY]:
println “Weekends are cool”
break
//a day between Monday and Friday
case Day.MONDAY..Day.FRIDAY:
println “Boring work day”
break
default:
println “Are you sure this is a valid day?”
}
注意,switch和case中能够使用不论什么对象,尤其是能够在case中使用List和范围,从而使分支满足多个条件(这点跟delphi有点象)。
同java5一样,groovy支持带构造器、属性和方法的enum:
enum Planet {
MERCURY(3.303e 23, 2.4397e6),
VENUS(4.869e 24, 6.0518e6),
EARTH(5.976e 24, 6.37814e6),
MARS(6.421e 23, 3.3972e6),
JUPITER(1.9e 27,7.1492e7),
SATURN(5.688e 26, 6.0268e7),
URANUS(8.686e 25, 2.5559e7),
NEPTUNE(1.024e 26, 2.4746e7)
double mass
double radius
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
void printMe() {
println “${name()} has a mass of ${mass} “
“and a radius of ${radius}”
}
}
Planet.EARTH.printMe()
16、 Elvis操作符
这是三目运算符“?:”的简单形式,三目运算符通常以这样的形式出现:
String displayName = name != null ? name : “Unknown”;
在groovy中,也能够简化为(由于null在groovy中能够转化为布尔值false):
String displayName = name ? name : “Unknown”;
基于“不反复”的原则,能够使用elvis操作符再次简化为:
String displayName = name ?: “Unknown”
17、 动态性
Groovy全部的对象都有一个元类metaClass,我们能够通过metaClass属性訪问该元类。通过元类,能够为这个对象添加�方法(在java中不可想象)!见以下的代码,msg是一个String,通过元类,我们为msg添加�了一个String 类中所没有的方法up:
def msg = “Hello!”
println msg.metaClass
String.metaClass.up = { delegate.toUpperCase() }
println msg.up()
通过元类,我们还能够检索对象所拥有的方法和属性(就象反射):
msg.metaClass.methods.each { println it.name }
msg.metaClass.properties.each { println it.name }
甚至我们能够看到我们刚才加入�的up方法。
我们能够通过元类推断有没有一个叫up的方法,然后再调用它:
if (msg.metaClass.respondsTo(msg, ‘up’)) {
println msg.toUpperCase()
}
当然,也能够判断它有没有一个叫bytes的属性:
if (msg.metaClass.hasProperty(msg, ‘bytes’)) {
println msg.bytes.encodeBase64()
}
18、 Groovy swing
到如今为止,我们的groovy一直都在控制台窗体下工作。假设你还不满足,当然也能够使用swingbuilder来构建程序:
import groovy.swing.SwingBuilder
import java.awt.BorderLayout
import groovy.swing.SwingBuilder
import java.awt.BorderLayout as BL
def swing = new SwingBuilder()
count = 0
def textlabel
def frame = swing.frame(title:‘Frame’, size:[300,300]) {
borderLayout()
textlabel = label(text:“Clicked ${count} time(s).”,
constraints: BL.NORTH)
button(text:‘Click Me’,
actionPerformed: {count ; textlabel.text =
“Clicked ${count} time(s).”; println “clicked”},
constraints:BorderLayout.SOUTH)
}
frame.pack()
frame.show()
怎么样?是不是跟java 中写swing程序非常象?
五、单元測试
1、 加入�junit
使用 Build PathàAdd Libraries… 把junit加入�到项目中。
2、 新建測试
使用 New à Junit Test Case 新建測试例程:PersonTest,在Class under test右边的Browserbutton,选择要进行測试的groovy类Person。
Finish,以下编写測试用例代码(我使用了Junit4):
import org.junit.*;
public class TestPerson {
@Test
public void testToString(){
Person p=new Person(); //注意由于groovy编译Person时默认全部属性为private
p.setName(“ddd”); //所以用set方法设置name属性而不用p.name=”ddd”
p.setAge(18);
Assert.assertEquals(“ddd-18”, p.toString());
}
}
执行Run AsàJunit Test,发现testToString通过測试。
3、使用groovy书写測试用例
除了使用Java来书写測试用例以外,我们也能够使用groovy书写。
New à Other à Groovy à Groovy Class,写一个类GroovyTestPerson:
import org.junit.*;
class GroovyTestPerson {
@Test
void testToString(){
Person p=new Person(“name”:“ddd”,“age”:18)
Assert.assertEquals(“ddd-18”, p.toString())
}
}
能够看到,这里使用的全然是Groovy风格的书写方式:不须要public,使用map參数构造对象。然而当你Run AsàJunit Test的时候,结果跟用java编写的測试用例没有什么两样。
这也充分说明了,groovy和java,除了语法不一样,本质上没有什么差别(对照.net framework中的C#和VB.net,它们除了语法不同外,本质上它们都使用CLR)。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/118753.html原文链接:https://javaforall.cn