《Groovy官方文档》1.3 Groovy和Java比较

原文地址     译文地址  译者:jackWang

Groovy语言一直在努力亲近Java开发人员。在设计Groovy语言的时候,我们遵循最小标新立异原则,努力让那些Java开发背景的开发者容易上手并学会。下面我们列举Groovy和Java的一些主要区别。

1 默认导入

下面的包和类是默认导入的,也就是说不必精确使用 import 语句来导入它们:

  • java.io.*
  • java.lang.*
  • java.math.BigDecimal
  • java.math.BigInteger
  • java.net.*
  • java.util.*
  • groovy.lang.*
  • groovy.util.*

2 动态方法(Multi-methods)

在Groovy里,方法的调用是在运行时动态决定。这一特性叫做运行时分发(runtime dispatch)或动态方法(multi-methods)。也就是说方法的最后调用是根据传入参数在运行时的类型所决定。在Java里,这一点是不一样的:在编译时就决定了方法的参数类型。

下面的代码,我们采用Java风格,在Groovy和Java都可以编译通过,但是运行结果不一样:

int method(String arg) {
    return 1;
}
int method(Object arg) {
    return 2;
}
Object o = "Object";
int result = method(o);

在Java里,结果是

assertEquals(2, result);

但是Groovy里,结果是

assertEquals(1, result);

原因是Java使用的是静态声明的类型信息,这里o被声明为Object,但是Groovy是在运行时决定,当方法最终被调用时,因为这里o实际是一个字符串,因此最终String版本的方法被调用。

译者注:译者之前也没有接触过Groovy语言,空闲时间也是有限的(姑且让我找这个借口吧,虽然这个借口很牵强,对待知识本来应该以一种严谨,求真的态度)因此这里有些专有名字可能翻译不是很准确,比如对Multi-methods的翻译。译者也不确定是否准确,因此附带了原文单词,请读者自行根据示例代码和上下文意思理解。如果找到准确的中文翻译恳请评论留言,以待修正。

3 数组初始化

在Groovy,{…}已经被用作闭包,也就是说你不能使用下面的语法创建数组(译者注:Java可以,并且很常用

int[] array = { 1, 2, 3}

你应该这样声明并初始化一个数组

int[] array = [1,2,3]

4 包范围可见性(Package scope visibility)

在Groovy里,省略字段的修饰符不会像Java一样使其成为包私有属性(package-private field)

class Person {
    String name
}

这里,我们创建了一个属性,它是私有的,而且自动关联了getter和setter方法。如果我们要创建一个包私有属性,可以添加@PackageScope注解来实现:

class Person {
    @PackageScope String name
}

5 ARM块

ARM(Automatic Resource Management 自动资源管理)块从Java7开始支持,但是Groovy不支持。相应地,Groovy依赖于闭包来实现类似的功能。示例:

Path file = Paths.get("/path/to/file");
Charset charset = Charset.forName("UTF-8");
try (BufferedReader reader = Files.newBufferedReader(file, charset)) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }

} catch (IOException e) {
    e.printStackTrace();
}

在Groovy里可以写成:

new File('/path/to/file').eachLine('UTF-8') {
   println it
}

或者也可以写成跟Java类似风格:

new File('/path/to/file').withReader('UTF-8') { reader ->
   reader.eachLine {
       println it
   }
}

6 内部类

Groovy遵循了Java的匿名内部类以及嵌套内的特点。但是它并没有完全依照Java语言规范,因此在使用前应该记住它们是有区别的。Groovy的实现和groovy.lang.Clouser类的风格有些类似,但也有不同点。比如在访问私有字段和方法以及局部变量没有final等。

6.1 静态内部类

这是一个静态内部类的例子:

class A {
    static class B {}
}

new A.B()

使用静态内部类是一个非常好的实践,如果你一定要使用内部类,建议优先考虑静态内部类。

6.2 匿名内部类

import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

CountDownLatch called = new CountDownLatch(1)

Timer timer = new Timer()
timer.schedule(new TimerTask() {
    void run() {
        called.countDown()
    }
}, 0)

assert called.await(10, TimeUnit.SECONDS)

6.3 创建非静态内部类实例

在Java里,你可以这样写:

public class Y {
    public class X {}
    public X foo() {
        return new X();
    }
    public static X createX(Y y) {
        return y.new X();
    }
}

Groovy不支持y.new X()语法,但你可以写成new X(y),像下面的代码:

public class Y {
    public class X {}
    public X foo() {
        return new X()
    }
    public static X createX(Y y) {
        return new X(y)
    }
}

特别注意,Groovy支持调用无参方法传入一个参数。那个参数的值将会是null。这个特性对于调用构造函数同样适用。可能会有人写new X(this)而不是new X(),这是不合法的。虽然我们还没有找到办法避免用户这样写。

7  拉姆达表达式

Java 8 支持拉姆达表达式和方法引用

Runnable run = () -> System.out.println("Run");
list.forEach(System.out::println);

Java8的拉姆达表达式或多或少被认为是匿名内部类。Groovy不支持这样的语法,但是可以使用闭包代替:

Runnable run = { println 'run' }
list.each { println it } // or list.each(this.&println)

8  GStrings

使用双引号修饰的字符串被解释为GString值。如果一个字符串里含有美元符号在Groovy和Java的编译器里将会产生编译错误。

当然,Groovy会自动在GString和String之间进行类型转换,就像Java可以接受一个Object参数然后检查其实际类型一样。

9  字符串和字符

在Groovy里,使用单引号修饰的被当成String类型,使用双引号修饰的可以当成GString类型或String类型。取决于字面常量。

assert 'c'.getClass()==String
assert "c".getClass()==String
assert "c${1}".getClass() in GString

如果声明是char类型,Groovy会自动将单个字符从String类型转换为char类型。如果被调用的方法声明的参数类型是char,我们需要强制类型转换为char类型。

char a='a'
assert Character.digit(a, 16)==10 : 'But Groovy does boxing'
assert Character.digit((char) 'a', 16)==10

try {
  assert Character.digit('a', 16)==10
  assert false: 'Need explicit cast'
} catch(MissingMethodException e) {
}

Groovy支持两种风格的类型转换,在转换成char类型的时候,当个字符和多个字符转换有些不一样。对于多个字符转换成char类型,Groovy会选择第一个字符,这一点不像C语言,会直接失败。

// for single char strings, both are the same
assert ((char) "c").class==Character
assert ("c" as char).class==Character

// for multi char strings they are not
try {
  ((char) 'cx') == 'c'
  assert false: 'will fail - not castable'
} catch(GroovyCastException e) {
}
assert ('cx' as char) == 'c'
assert 'cx'.asType(char) == 'c'

10 ==的行为

在Java里,==意味着基本类型相等或对象类型相等。在Groovy里,==会转换成a.compareTo(b)==0,如果他们是Comparable,就是使用a.equals(b),否则检查基本类型,也就是is,比如a.is(b)

11  不同的关键字

Groovy比Java有更多的关键字,请不要把它们当变量名使用

  • in
  • trait
时间: 2024-10-31 16:44:22

《Groovy官方文档》1.3 Groovy和Java比较的相关文章

《Groovy官方文档》1.1 下载Groovy

在本模块(本模块指Groovy官网Download模块),你可以下载Groovy的发布版本(源码和二进制安装包),Windows安装包(只有部分版本)和相关文档. 所有的下载源都是托管在Groovy的Bintray库.成为该站点用户具有投票,下载代码以及发布新版本的权限. Mac,Linux用户或者使用Cygwin的用户,可以使用SDKMAN(The Software Development Kit Manager)来下载和配置任意版本的Groovy.这样会使事情变得很简单.基本的操作在下文将会

《Groovy官方文档》1.2安装Groovy

原文地址  译文地址  译者:jackwang 1 下载 在本模块中(本模块指Groovy官网Download模块),你可以下载Groovy的发布版本(源码和二进制安装包),Windows安装包(只有部分版本)和相关文档.Mac OSX,Linux以及Cygwin用户,可以使用GVM(the Groovy enVironment Manager)方便快捷下载安装和配置任意Groovy版本.简要的说明见下文. 1.1 稳定版 下载ZIP:二进制版本 |源码 下载文档:JavaDoc和压缩在线文档

《Groovy官方文档》Groovy开发套件-使用IO

原文链接   译文链接   译者:JackWang Groovy开发套件 第一部分 1 I/O 的使用 Groovy提供了丰富的方法来操作IO流.当然你也可以使用标准的Java代码来进行这些操作.但是Groovy提供了更多方便的方式来操作文件,流- 你可以先看看下面列举的一些方法: the io.File class : http://docs.groovy-lang.org/latest/html/groovy-jdk/java/io/File.html the io.InputStream

《Groovy官方文档》Groovy开发套件-使用集合

Groovy开发套件 第二部分 2 使用集合 Groovy提供了各种类型的原生态集合支持,包括list,  maps  和 ranges .它们大多数都是基于Java集合类型,同时在Java集合类型中一些废弃的方法在Groovy开发套件中也可以找到. 注:译者也是第一次接触Groovy,由于时间和水平有限(姑且让译者使用这个理由吧,对待知识本应该一丝不苟)部分专有名词可能翻译不准确甚至有误(读者阅读的过程中最好能参考原文),恳请读者不吝留言指出,谢谢! 2.1 Lists 2.1.1 list

《Groovy官方文档》3.4 开发环境支持

许多 IDE 和文本编辑器都提供了 Groovy 支持. IDE/编辑器 特性 语法高亮 自动补全 重构辅助 Groovy Eclipse Plugin Y Y Y IntelliJ IDEA Y Y Y Netbeans Y Y Y Groovy and Grails Toolsuite Y Y Y Groovy Emacs Modes Y N N TextMate Y N N Vim Y N N UltraEdit Y N N 转载自 并发编程网 - ifeve.com

jQuery 1.4官方文档详细讲述新特性功能

为了庆祝jQuery的四周岁生日, jQuery的团队荣幸的发布了jQuery Javascript库的最新主要版本! 这个版本包含了大量的编程,测试,和记录文档的工作,我们为此感到很骄傲. 我要以个人的名义感谢 Brandon Aaron, Ben Alman, Louis-Rémi Babe, Ariel Flesler, Paul Irish, Robert Kati?, Yehuda Katz, Dave Methvin, Justin Meyer, Karl Swedberg, and

TestNG官方文档中文版(9)-重复失败测试,junit测试,jdk1.4支持

5.10 - Rerunning failed tests 套件中的测试失败时,每次testNG都会在输出目录中创建一个名为testng-failed.xml 的文件.这个xml文件包含只重新运行这些失败的测试方法的必要信息,容许只运行这些 失败的测试而不必运行全部测试.因此,一种典型的情况将是这样: java -classpath testng.jar;%CLASSPATH% org.testng.TestNG -d test-outputs testng.xml java -classpat

TestNG官方文档中文版(6)-参数

5.5 - Parameters 测试方法不要求是无参数的.你可以在每个测试方法上使用任意数量的参数,并指示 testNG传递正确的参数. 有两种方式用于设置参数:使用testng.xml或者编程式. 5.5.1 - Parameters from testng.xml 如果你要为你的参数使用简单值,你可以在你的testng.xml中明确指定: @Parameters({ "first-name" }) @Test public void testSingleString(String

TestNG官方文档中文版(3)-testng.xml

TestNG的官方文档的中文翻译版第3章,原文请见 http://testng.org/doc/documentation-main.html 3 - testng.xml 调用TestNG由几种不同方法: * 使用testng.xml文件 * 使用ant * 从命令行 这节描述testng.xml的格式(文档的后面会讲到ant和命令行). 当前testng.xml的DTD文件可以从官方找到:http://testng.org/testng-1.0.dtd.( 为了方便使用,你可能更喜欢浏览HT