Groovy文档翻译——Groovy与JAVA的异同

与Java的不同点

Groovy尝试对Java开发者尽可能的自然。我们在设计Groovy的时候遵循最小惊奇的原则,尤其是原先是Java后台但现在学习Groovy的开发者。

在这里我门列出了Java和Groovy的最主要的区别。

1.默认导入

以下的这些这些包和类默认被导入了,所以您不需要特地使用一个明确的***import***语句去使用他们。

  • java.io.*

  • java.lang.*

  • java.math.BigDecimal

  • java.math.BigInteger

  • java.net.*

  • java.util.*

  • groovy.lang.*

  • groovy.util.*

2.多重方法

在groovy中,被调用的方法在运行的时候确定。这被称作运行时分发或者多重方法。这就意味着那个方法将在运行的时候基于他的参数类型被决定
在Java中,方法的选择是基于Groovy的对立面的:方法在编译的时候基于声明的类型被决定。

这下面的代码,能够同时被编译成Java和Groovy的,但是却有着不同的行为:

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将会在运行时方法被调用的时候进行选择。由于他被声明为了String类型,所以参数类型为String的方法被调用了。

3.数组的初始化

在Groovy形如{ … }的语句被视作闭包。这意味着您不能使用这个语法创建数组(如下所示是错误的):

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

实际上您不得不使用以下的语法:

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

4.包可见的作用域

在Groovy里面,省略成员变量修饰符并不会像Java一样变成一个包私有的成员变量:

class Person {
    String name
}

相对的他被用来创建一个属性,这意味着他被声明为一个私有的成员变量,一个对应的Getter方法和一个对应的Setter方法。

您也可以通过用@PackageScope修饰一个包私有的成员变量使他变成包公有的成员变量。

class Person {
    @PackageScope String name
}

###5.ARM(自动资源回收管理)语句块

从Java 7开始的自动资源回收管理语句块(Automatic Resource Management)在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();
}

能够被写成下面这样:

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.内部类

匿名内部类和嵌套类的实现遵循Java的指导,但是您不应该在使用Java语言规范的同时坚决否认不同的编程规范。这个实现的完成看起来很想我们为groovy.lang.Closure做的:既有一些好处但也有一些不同。例如允许访问私有成员变量和方法可能导致一些问题,但是另一方面来说局部变量并不需要被声明成为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()而不是new X(this)的时候是很危险的,由于我们还没有找到一个好的方法去防止这个问题 。

7.Lambda表达式

Java 8 支持Lambda表达式和方法引用:

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

Java 8的Lambda表达式可以或多或少的被看作是匿名内部类,Groovy并不支持这种语法但是相对的Groovy有闭包:

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

8.GStrings

由于双引号字符串字面量被解释为GString值,当Groovy和Java编译器编译一个包含"$"字符的字符串字面量的类Groovy可能由于编译错误而失败,或者产生一些微妙的有些不同的代码。

通常情况下,如果一个API声明参数类型为GString或String时Groovy将会自动在这两中类型间进行转换,当心接受一个Object最为参数的Java APIS并且检查实际的类型。

9.字符串和字符字面量

单引号字面量在Groovy被用作String类型,而双引号字面量将会依据在字面量中是否有字符串插值被视作String类型或者GString类型。

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

Groovy仅仅在分配一个char变量的时候才会自动的将一个单字符字符串(如’c’在groovy中他的类型并不是char而是String)装换成字符类型变量(char类型)。在调用有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支持两种风格的类型转换,但是当转换一个多字符字符串的时候他们有一些微妙的不同。Groovy风格的转换更加的宽松,而C风格的转换(Java强制装换的那种风格)将会由于异常而失败。

// 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.原始类型和包装类(int和Integer等)

由于在Groovy中一切都是对象,他会自动包装原生类型。由于这个原因,他并不会遵循Java扩宽类型优先与包装的原则。这里有一个使用int的例子:

int i
m(i)

void m(long l) {                //(1) 
  println "in m(long)"
}

void m(Integer i) {         //(2)
  println "in m(Integer)"
}

(1)这是Java会调用的方法,因为扩宽类型优先于类型自动拆箱。
(2)只是Groovy实际上会调用的方法 ,因为所有原始类型都被他们的包装类型替换了。

11.==的行为

在Java中意味着原始类型的值相等(int,double等未包装的类型)或者对象的指针相等。在Groovy,如果他们是Comparable接口的实现则**被翻译成a.compareTo(b)==0**,否则就是a.equals(b)。为了检查指针是否相等,请使用关键字is,例如:a.is(b)

12.转换

Java使用自动扩宽和狭窄的转换

                               Table 1.Java 转换
目标类型
原类型booleanbyteshortcharintlongfloatdouble
boolean-NNNNNNN
byteN-YCYYYY
shortNC-CYYYY
charNCC-YYYY
intNCCC-YTY
longNCCCC-TT
floatNCCCCC-Y
doubleNCCCCCC-

行标签为原类型,列标签为目标类型。'Y’表明Java能够自动转换的类型。'C’表明当有显示转换的时候Java能够转换的类型。'T’表示Java能够转换的类型但是数据会被截断。'N’表示Java不能够转换的类型。

Groovy在这基础上扩展了很多。

                              Table2.Groovy 转换
目标类型
原类型booleanBooleanbyteByteshortShortcharCharacterintIntegerlongLongBigIntegerfloatFloatdoubleDoubleBigDecimal
boolean-BNNNNNNNNNNNNNNNN
BooleanB-NNNNNNNNNNNNNNNN
byteTT-BYYYDYYYYYYYYYY
ByteTTB-YYYDYYYYYYYYYY
shortTTDD-BYDYYYYYYYYYY
ShortTTDTB-YDYYYYYYYYYY
charTTYDYD-DYDYDDYDYDD
CharacterTTDDDDD-DDDDDDDDDD
intTTDDDDYD-BYYYYYYYY
IntegerTTDDDDYDB-YYYYYYYY
longTTDDDDYDDD-BYTTTTY
LongTTDDDTYDDTB-YTTTTY
BigIntegerTTDDDDDDDDDD-DDDDT
floatTTDDDDTDDDDDD-BYYY
FloatTTDTDTTDDTDTDB-YYY
doubleTTDDDDTDDDDDDDD-BY
DoubleTTDTDTTDDTDTDDTB-Y
BigDecimalTTDDDDDDDDDDDTDTD-

行标签为原类型,列标签为目标类型。'Y’表明Groovy能够自动转换的类型,'D’表示Groovy能够通过显示转换或者动态编译转换的类型,'T’表示Groovy能够转换的类型但是数据会被截断。'B’表示一个装箱/拆箱操作。'N’表示Groovy不能够转换的类型。

当转换成boolean/Boolean时截断使用Groovy Truth。从数字到字符的转换将Number.intvalue()转换成char。当从Float或者Double转换时Groovy使用BigIntegerBigDecimal进行构造,否则使用**toSting()**构造。
java.lang.Number定义了其他的转换的行为。

13.其他关键字

Groovy拥有比java更多的关键在。请不要把他们作为变量名。如下:

  • as

  • def

  • in

  • trait

github地址https://github.com/15026967693/DocumnentCompile

有心情就翻

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值