前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Groovy与java的不同之处

Groovy与java的不同之处

作者头像
三产
发布2021-01-13 10:59:42
1.5K0
发布2021-01-13 10:59:42
举报

默认import

在Groovy中,下面这些包会默认引入。 - java.io.* - java.lang.* - java.math.BigDecimal - java.math.BigInteger - java.net.* - java.util.* - groovy.lang.* - groovy.util.*

Multi-methods(运行时调度)

Groovy调用方法是在运行时进行的选择,是根据参数的类型来获取相应的方法。而java则是在编译时根据声明的类型选择相应要执行的方法。例如以下情况:

代码语言:javascript
复制
int method(String arg) {
    return 1;
}
int method(Object arg) {
    return 2;
}

对于以上两个方法进行调用

代码语言:javascript
复制
Object o = "Object";
int result = method(o);
System.out.println(result);

在java中运行结果为 2 在Groovy中运行结果为 1【因为Groovy在运行时判断出o是String类型】

数组初始化

在Groovy中{…}是留给闭包使用的,所以声明数组时不能像java一样使用

代码语言:javascript
复制
int[] array = { 1, 2, 3}

而必须使用

代码语言:javascript
复制
int[] array = [1,2,3]

包可见性

代码语言:javascript
复制
public class Person {
    String name;
    public static void main(String[] args) {
       Person p = new Person();
       p.setName("123");
       System.out.println(p.getName());
       System.out.println(p.name);
    }
}

对于上面的代码,在java中

代码语言:javascript
复制
p.setName("123"); 
System.out.println(p.getName());

这两行会报错。因为java默认name为包访问权限,且getter setter需要自己生成。 而在Groovy中,上面的代码可以正常运行。这是因为Groovy会自动为name字段添加getter setter。 相当于如下效果:

代码语言:javascript
复制
public class Person {
    @PackageScope String name
}

ARM锁

ARM (Automatic Resource Management 自动资源管理)锁在java7是不支持的。Groovy通过闭包提供了多种实现,例如

代码语言:javascript
复制
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中可以这样写:

代码语言:javascript
复制
new File('/path/to/file').eachLine('UTF-8') {
   println it
}

或者更接近java的写法:

代码语言:javascript
复制
new File('/path/to/file').withReader('UTF-8') { reader ->
   reader.eachLine {
       println it
   }
}

内部类

Groovy的内部类以及嵌套类遵循java的规范,但是有一定的差异。Groovy使其更符合闭包的写法,坏处是访问私有字段和方法可以成为一个问题,好处是本地变量无须是final的。

静态内部类

代码语言:javascript
复制
class A {
    static class B {}
}

new A.B()

Groovy推荐使用静态内部类。

匿名内部类

代码语言:javascript
复制
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)

创建非静态内部类的实例

在java中:

代码语言:javascript
复制
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),例如下面的例子。需要注意y为null的情况,Groovy官方没有找到合适的解决方法

代码语言:javascript
复制
public class Y {
    public class X {}
    public X foo() {
        return new X()
    }
    public static X createX(Y y) {
        return new X(y)
    }
}

lambdas

java 8支持lambdas和方法引用

代码语言:javascript
复制
Runnable run = () -> System.out.println("Run");
list.forEach(System.out::println);

Java 8 lambdas可以或多或少地认为是匿名内部类的写法。Groovy不支持这种语法,可以使用闭包的写法代替:

代码语言:javascript
复制
Runnable run = { println 'run' }
list.each { println it } // or list.each(this.&println)

GStrings

在Groovy中,双引号字符串会被解释为GString值。 使用Groovy编译器 编译包含的字符串可能会发生错误,或者会与java编译器的编译结果有些许不同(在Groovy中用于插入文字使用,”b{a}”相当于”b”+a 包含 的字符串如果不是正常格式的

While typically, Groovy will auto-cast between GString and String if an API declares the type of a parameter, beware of Java APIs that accept an Object parameter and then check the actual type.哪位英语达人给纠正一下呗】

String and Character字符

在Groovy中,单引号的字符用于String,双引号的字符为String或GString取决于字符中是否有插值的情况:

代码语言:javascript
复制
assert 'c'.getClass()==String
assert "c".getClass()==String
assert "c${1}".getClass() in GString

当将单引号字符分配给char类型时,Groovy会自动将String类型(单引号字符在Groovy中默认是String类型)转换为char类型。当调用参数类型是char的方法时,我们需要明确字符的类,或者确保类型已经转换。

代码语言:javascript
复制
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) {
 println e.getMessage()
}

在上面的代码中assert Character.digit(‘a’, 16)==10会报错,就是因为没有明确表明’a’的类型。 Groovy支持两种转换char类型的风格

代码语言:javascript
复制
// 对于单个字符,两种转换风格相同
assert ((char) "c").class==Character
assert ("c" as char).class==Character

// 对于多字符,两者有所差别
//第一种风格会报错,而第二种风格则会取第一个字符转为char类型
try {
  ((char) 'cx') == 'c'
  assert false: 'will fail - not castable'
} catch(GroovyCastException e) {
    println e.getMessage()
}
assert ('cx' as char) == 'c'
assert 'cx'.asType(char) == 'c'

==操作符

在java中 == 用于判读 基本类型或者对象指向 是否相同。在Groovy中,Groovy 当a、b实现Comparable时 a == b 解释为a.compareTo(b)== 0,未实现Comparable则解释为a.equals(b),检查两者是否是同一对象应该使用 is,例如 a.is(b)。

关键字

在Groovy中in、trait也是关键字

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015/08/12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 默认import
  • Multi-methods(运行时调度)
  • 数组初始化
  • 包可见性
  • ARM锁
  • 内部类
    • 静态内部类
      • 匿名内部类
        • 创建非静态内部类的实例
        • lambdas
        • GStrings
        • String and Character字符
        • ==操作符
        • 关键字
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档