`
jboy
  • 浏览: 8923 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

Groovy编程风格和语言特性指南(针对Java开发人员)

阅读更多

原文 http://groovy.codehaus.org/Groovy+style+and+language+feature+guidelines+for+Java+developers

Groovy编程风格和语言特性指南(针对Java开发人员

作为一个Java开发人员,当/开始学习Groovy,总是会用Java方式循序渐进地学习Groovy以使/的工作效率提高和写更地道的Groovy代码。本文的目的是引导这类开发人员学习一些常用的的Groovy语法风格,学习新的运算符,新的特性闭包,等等。不是详细描述,只能作为一个快速的介绍,和进一步学习的基础部分,欢迎添加,丰富该文档

没有分号

对于一个C / C + + / C/ Java背景的开发人员,我们是如此习惯使用分号,它们无处不在。更糟的是,Groovy支持99Java的语法,并且某些时候复制一些Java代码到你的Groovy程序里是如此容易,这样你的世界就会充斥着无数的分号。但是......Groovy中,分号是可选的,你可以忽略它们,将其删除更地道Groovy风格

可选关键字return

Groovy中,方法体内的最后一个表达式会被返回,而不需要return关键字。尤其是针对简短的方法和闭包省略return显得更简洁

String toString() {return "a server" 

String toString() {"a server" }

但有时候,这并不易于理解当你使用一个变量,并且这个变量出现在多行:

def props() {

def m1 = [a:1, b:2

m2 = m1.findAll { k, v -> v %2 ==0 

m2.c =3 

m2

}

在这种情况下,无论是最后一个表达式之前加上一个换行还是显式地使用return,可能会产生更好的可读性。

我自己,有时使用return关键字,有时没有,它往往是一个品味的问题。例如在使用闭包时,我们通常会省略return所以,即使关键字是可选的,但是不意味着强制性的,如果你认为它妨碍你代码的可读性就别使用

注意如果使用def关键字而不是某个具体类型定义的方法时,有时返回的最后一个表达式可能会让你吃惊。所以通常更喜欢使用一个特定的返回类型,如void某个类型。在我们上面的例子中,假设我们忘了把m2最为最后一条语句返回,最后的表达m2.c == 3,这将返回... 3,而不是期望map

有一些语句,如if / else语句,try / catch语句,也可以返回一个值,因为他们也可以有一个最后表达式

def foo(n) {i

f(n ==1) {

"Roshan" 

}else {

"Dawrani" 

}

assert foo(1) =="Roshan"

assert foo(2) =="Dawrani"

Def具体类型

我们正在谈论def类型,我经常看到开发人员'def'具体类型一起使用。但是,def在这里是多余的。需要做出一个选择,要么使用def,要么使用一个具体类型。

所以,不要这样写:

def String name ="Guillaume"

较好的是这样

String name ="Guillaume"

Groovy中,def表明的实际类型是Object(这样你就可以def定义的变量分配任何对象,和在用def定义的方法里返回任何类型的对象)。

默认public修饰符

默认情况下,Groovy中认为,类和方法是具有public访问权限的。所以,你没有必要使用public修饰符。只有当它不是public的,你应该使用可见性修饰符。

因此,对于以下写法

public class Server { public String toString() {return "a server" } }

更简洁的写法是

class Server { String toString() {"a server" } }

你可能想知道包范围的可见性修饰符,事实上,Groovy允许省略public即表示默认情况下不支持包范围的可见性,但实际上一个特殊的Groovy注解,使用的包可见性

class Server { @PackageScope Cluster cluster }

省略括号

Groovy允许你省略顶级层次表达式的圆括号,如用println的命令:

println "Hello

method a, b

VS

println("Hello") 

method(a, b)

当一个闭包是一个方法调用的最后一个参数,如在使用Groovyeach函数,你可以把闭包放在括号外,甚至可以省略括号:

list.each( { println it } ) 

list.each(){ println it } 

list.each { println it }

总是喜欢第三种形式,这更自然,一对空括号只是无用的语法噪音!

有一些情况,Groovy并不是允许你删除括号。正如我所说的,顶级的表达式可以省略,但嵌套的方法调用,或者赋值语句的右边(?可以省略?),你不能忽略括号

def foo(n) { n }

println foo1 // won't work

def m = foo1

类,一等公民

后缀.class有点像Java的的instanceof,但在Groovy已不再需要

例如:

connection.doPost(BASE_URI +"/modify.hqu", params, ResourcesResponse.class)

使用的GString和一等公民,写法如下

connection.doPost("${BASE_URI}/modify.hqu", params, ResourcesResponse)

GetterSetter

Groovy中,一个gettersetter方法形成了我们所谓的属性,并提供了一个捷径来访问和设置这些属性Java的调用方式不同,你可以使用一个类似字段访问的方式

resourceGroup.getResourcePrototype().getName() == SERVER_TYPE_NAME 

resourceGroup.resourcePrototype.name == SERVER_TYPE_NAME 

resourcePrototype.setName("something")

resourcePrototype.name = "something"

Groovy编写bean,通常被称为POGOsPlain and Old GroovyObjects),你不必创建字段getter / setter,编译器会替你做。

因此,不要这样写

class Person { 

private String name 

String getName() {

return name 

}

void setName(String name) {

this.name = name 

}

可以简单的写

class Person { String name }

正如你看到,一个独立的没有修饰符字段实际上使得Groovy编译器生成一个私有字段相应gettersetter

当然,在Java使用POGOsgettersetter确实存在,并可以照常使用。

尽管编译器创建通用的getter / setter方法的逻辑,然而如果你愿意在这些getter / setter方法做任何附加的或不同的逻辑,你必须可以提供它们,编译器将使用你的逻辑,而不是默认生成。

使用命名参数和默认构造函数初始化bean

一个bean,如:

class Server { String name; Cluster cluster }

可以使用命名参数的默认构造函数(首先构造函数被调用,然后依次调用setter):

def server =new Server(name:"Obelix", cluster: aCluster)

而不是声明后调用各个setter

def server =new Server() 

server.name ="Obelix"

server.cluster = aCluster

使用with()重复操作同一个bean

使用命名参数的默认构造函数创建新的实例有趣,但如果你正在更新的一个得到的实例,你一定要重复一遍又一遍的'server'前缀?不,多亏了Groovy给所有对象添加的with()方法:

server.name = application.name 

server.status = status 

server.sessionCount = 3 

server.start() 

server.stop()

VS

server.with { 

name = application.name 

status = status 

sessionCount = 3 

start() 

stop() 

}

Equals ==

Java==其实是Groovyis()方法,Groovy==是一个聪明的equals()方法!

要比较的对象引用,你应该使用a.is(B)而不是==

对于通常的equals()比较,你应该更喜欢Groovy==,因为它也可以避免NullPointerException异常,无论左边或者右边的变量是不是null

不要这样写:

status !=null && status.equals(ControlConstants.STATUS_COMPLETED)

这样做:

status == ControlConstants.STATUS_COMPLETED

GString内插变量,多行)

Java中我们经常使用双引号,加好和\n换行符来使用字符串和变量串联。利用内插字符串(称为GString),这样的字符串看起来更好并且减少打字的痛苦:

throw new Exception("Unable to convert resource: " + resource)

VS

throw new Exception("Unable to convert resource: ${resource}")

在大括号中,你可以把任何一种表达方式放入其中,而不仅仅是变量。对于简单变量或变量的属性,你甚至可以丢弃的大括号:

throw new Exception("Unable to convert resource: $resource")

你甚至可以延迟评估这些表达式,使用闭包的符号$ { -> resource}。当GString的将被强制转换为String,它会评估闭包,并获得toString()的返回值的。示例:

int i =3 

def s1 ="i's value is: ${i}"

def s2 ="i's value is: ${-> i}" 

i++

assert s1 =="i's value is: 3" // eagerly evaluated, takes the value on creation

assert s2 =="i's value is: 4" // lazily evaluated, takes the new value into account

Java字符串和其连接的表达Java是很冗长的

throw new PluginException("Failed to execute command list-applications:" +

" The group with name " 

parameterMap.groupname[0] +

" is not compatible group of type " 

SERVER_TYPE_NAME)

您可以使用\延续字符(这是一个多行字符串):

throw new PluginException("Failed to execute command list-applications: \ 

The group with name ${parameterMap.groupname[0]} \ 

is not compatible group of type ${SERVER_TYPE_NAME}")

或者使用多行三重引号的字符串:

throw new PluginException("""Failed to execute command list-applications: 

The group with name ${parameterMap.groupname[0]} 

is not compatible group of type ${SERVER_TYPE_NAME)}""")

也可以在该字符串上调用stripIndent()方法剥离出现在多行的字符串的左侧的缩进

另请注意Groovy中的单引号和双引号的区别:单引号总是创建Java字符串,没有内插变量,而双引号可以创建Java字符串,也可以创建GString当有内插变量

对于多行字符串,你可以使用三个引号,也就是说:GString三双引号单纯的字符串三个单引号。

原生语法的数据结构

Groovy提供原生的语法来构造如listmap,正则表达式,范围值等数据结构。确保在你的Groovy程序利用它们。

下面是一些例子:

def list = [1,4,6,9]

// by default, keys are Strings, no need to quote them

// you can wrap keys with () like [(variableStateAcronym): stateName] to insert a variable or object as a key.

def map = [CA:'California', MI:'Michigan']

def range =10..20

def pattern = ~/fo*/

// equivalent to add()

list <<5

// call contains()

assert 4 in list

assert 5 in list

assert 15 in range

// subscript notation

assert list[1] ==4 

// add a new key value pair

map << [WA:'Washington']

// subscript notation

assert map['CA'] =='California'

// property notation

assert map.WA =='Washington' 

// matches() strings against patterns

assert 'foo' =~ pattern

Groovy的开发工具包

当你需要对集合进行迭代并关注在数据结构上时Groovy中提供各种额外的方法,包装了Java的核心数据结构,就像each{}find{}findAll{}every{}collect{}inject{}。这些方法添加了函数编程的风格,并编写复杂的算法更容易。由于语言的动态性质,经过包装,许多新的方法应用到不同类型。你可以找到很多关于字符串,文件,流,集合的非常有用的方法,更多请看

http://groovy.codehaus.org/groovy-jdk/

switch的威力

GroovyswitchC-风格的语言--通常只接受基本类型功能更强大。Groovyswitch语句接受几乎任何一种类型。

def x =1.23

def result =""

switch (x) {

case "foo": result ="found foo" 

// lets fall through 

case "bar": result +="bar" 

case [4,5,6,'inList']: 

result ="list" 

break 

case 12..30

result ="range" 

break 

case Integer: 

result ="integer" 

break 

case Number: 

result ="number" 

break 

default: result ="default"

}

assert result =="number"

更普遍的是,具有isCase()方法的类型,也可以出现在case子句中。

Import使用别名

Java中,当使用不同包里的具有相同的名称的两个类时,如java.util.Listjava.awt.List,你可以导入一个类,但另一个必须使用全名

还有有时候在你的代码中,当频繁使用一个很长的类名,代码变得冗长。

为了改善这种情况下,Groovy允许import使用别名:

import java.util.List as juList

import java.awt.List as aList

import java.awt.WindowConstants as WC

还可以导入静态的方法:

import static pkg.SomeClass.foo

foo()

GroovyTrue

所有对象都可以被转成一个布尔值:一切nullvoidempty都是false,如果不是,则计算结果为true

因此,if (name) {}写法完全可以替代if (name != null && name.length > 0) {}集合类也是如此。

于是可以在类似while()if(),三元运算符,Elvis操作符(见下文)等中运用此技巧

甚至可以自定义的Groovytrue,通过添加一个的布尔asBoolean()方法到你的

安全引用导航

Groovy支持.运算符的一个变体,可以安全导航一个对象图。

Java中,当你对对象路径图中的一个节点兴趣,需要检查是否为NULL往往导致写出来的复杂的if语句或嵌套的if语句:

if (order !=null) {

if (order.getCustomer() !=null) {

if (order.getCustomer().getAddress() !=null) { 

System.out.println(order.getCustomer().getAddress()); 

}

}

}

利用?.安全引用操作符,可以简化代码:

println order?.customer?.address

整个调用链中检查空值,任何元素为null都不会抛出NullPointerException异常,如果有一个为null返回值也是null

断言

要检查参数,返回值,以及更多的东西,你可以使用“assert”语句。

Java的断言相反,断言并不需要被激活才能工作,Groovy中它总是打开的

def check(String name) {

// name non-null and non-empty according to Groovy Truth 

assert name

// safe navigation + Groovy Truth to check 

assert name?.size() >3

}

您还可以看到Groovy强大的断言语句提供的漂亮的输出被断言的每个子表达式的值图形视图。

Elvis操作符提供默认值

Elvis操作符是一种特殊的三元运算符的快捷方式,用于方便的使用默认值。

我们经常要这样写代码:

def result = name !=null ? name :"Unknown"

由于Groovy特性,空检查name!=null可以简化name

再进一步,因为你总是返回name与其在这个三元表达式重复name两次,不如我们以某种方式删除问号和冒号之间的部分,通过使用Elvis操作符,上述代码变成:

def result = name ?:"Unknown"

捕获任何异常

如果你真的不关心try代码块内抛出的异常,你可以简单地捕捉所有的异常并忽略其类型。但是不是像下面一样捕捉throwables

try {// ...}catch (Throwable t) {// something bad happens}

而是捕捉所有东西('任何''所有',或任何让你觉得这是一切的东西):

try {// ...}catch (any) {// something bad happens}

关于强弱类型的建议

最后我会以如何使用可选的类型结束本文Groovy中你可以自己决定是否使用显式的强类型,或者使用def

我有一个相当简单的经验法则:每当你写的代码会被其他人当作一个公共API使用,你应该总是使用强类型,它有助于增强规约,避免可能的传递错误类型参数,提供更好的文档,也有利于IDE的代码完成;如果代码仅是供自己使用,如私有方法,或当IDE可以很容易地推断出的类型,那么你可以自由决定

0
8
分享到:
评论

相关推荐

    Groovy用户指南

    Groovy不仅支持传统的面向对象编程特性,还支持函数式编程风格,这使得它成为Java平台上一个非常有用的工具。此外,Groovy还有丰富的元编程能力,可以极大地提高开发效率。 #### 二、Groovy的基础语法 1. **变量...

    apache-groovy-sdk-2.5.15.zip

    这款SDK(Software Development Kit)包含了Groovy语言的运行环境和开发工具,是开发人员进行Groovy编程的基础。 Groovy作为一个面向对象的、动态类型的JVM(Java Virtual Machine)语言,它允许开发者以更少的代码...

    apache-groovy-sdk-2.4.12.zip

    Apache Groovy SDK 2.4.12 是一个完整的开发工具包,用于使用Groovy编程语言进行开发。Groovy是一种动态、灵活的面向对象编程语言,设计为与Java平台紧密集成,可以无缝地与Java代码互操作。它具有简洁的语法,支持...

    groovy学习大礼包

    Groovy是一种动态、灵活的编程语言,它是Java平台上的一个强大工具,被广泛用于脚本编写、自动化任务、构建工具以及服务器端应用开发。Groovy结合了Java的面向对象特性和Python、Ruby的简洁语法,使得它在开发过程中...

    Groovy in Action.pdf

    《Groovy in Action》是一本深入探讨Groovy编程语言的专业书籍,它为开发者提供了一条通往Groovy世界的全面路径。Groovy,作为一种动态、灵活的Java平台语言,因其简洁的语法和强大的功能,被广泛应用于脚本编写、...

    Grails-开源框架---使用指南.pdf与Groovy入门经典(中文).pdf(2合一)

    Groovy 是一种面向对象的、动态的、JVM上的编程语言,它与Java高度兼容,可以直接调用Java库,同时引入了Python和Ruby等动态语言的简洁特性。 1. **动态性:** Groovy 支持动态类型,允许在运行时改变变量类型,...

    Groovy in Action

    《Groovy in Action》是一本专注于Groovy编程语言的权威指南,由Dierk Koenig、Andrew Glover、Kris Coppieters和Paul King等人撰写,于2006年首次发布,并在2007年进行了更新。这本书旨在帮助读者深入理解Groovy...

    Groovy in action

    《Groovy in Action》不仅是一本全面介绍Groovy编程语言的书籍,更是一部深入探索Groovy特性和应用场景的宝典。无论是初学者还是经验丰富的开发者,都能从这本书中获得宝贵的见解和技巧,帮助他们在使用Groovy时更加...

    Groovy In Action

    《Groovy In Action》这本书是Groovy编程语言的权威指南,深入浅出地介绍了这个Java平台上的强大脚本语言。Groovy,作为一种简洁、灵活且动态的开发语言,旨在提高开发效率,尤其在构建脚本、自动化任务、领域特定...

    精通 Groovy 中文教程

    - **易用性**:Groovy引入了诸如闭包、元编程等高级特性,提高了开发效率。 #### 二、Groovy的核心概念 本节将介绍Groovy中的几个核心概念,包括本地集合、内置正则表达式和闭包等。 **本地集合**: - Groovy中...

    begining groovy and grails

    4. **插件和工具**:介绍常用的Grails插件和开发工具,如Spring Security Core、Cache、Rest等,以及如何利用它们提升应用性能和安全。 5. **部署和测试**:涵盖Grails应用的部署策略和测试方法,确保应用的稳定性和...

    Groovy InAction

    《Groovy InAction》是一本深受Groovy社区推崇的教程,它由Groovy官方网站推荐,继承了Action系列图书的一贯特点,深入浅出地讲解了Groovy编程语言的各个方面。这本书旨在帮助开发者全面掌握Groovy,提升在Java平台...

    Groovy Refcards

    这份“Groovy Refcards”文档为我们提供了Groovy语言的基本语法和关键特性的一个快速参考指南,下面我们将深入探讨这些核心知识点。 #### 一、语法基础 - **`as`**:用于类型转换,使变量或表达式能够被当作另一种...

    24小时掌握Java编程(英文)

    - **Java语言的历史与发展**: Java是由Sun Microsystems开发并在1995年发布的高级编程语言。 - **Java的特点**: Java是一种面向对象的语言,具有平台独立性、安全性、可移植性和高性能等特点。 - **Java的应用领域**...

    grails-docs-2.3.5.zip

    2. **Groovy语言**:Groovy是JVM上的动态编程语言,语法简洁,易于学习,同时具有静态类型的特性,支持面向切面编程(AOP)和函数式编程风格。 3. **Grails文档**:在"grails-docs-2.3.5.zip"中,包含的文档可能...

    Grails入门指南 gswg_source

    Groovy是Java平台上的一个面向对象的脚本语言,它具有简洁的语法和强大的元编程能力,使得Grails框架能够实现快速迭代和低代码量的开发模式。 Grails框架构建在一系列成熟的开源技术之上,包括: 1. **Spring框架*...

Global site tag (gtag.js) - Google Analytics