Groovy源代码分析(十三)

2021SC@SDUSC

Groovy与Java的主要区别

分析了这么久的Groovy,最后我们来总结一下Groovy与我之前学习的Java的主要区别。

默认 imports

所有这些包和类都是默认导入的,你不必使用显式import语句来使用它们:

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

额外的关键字

Groovy中还要比Java多几个关键字。 不要将它们用于变量名称等。

  • as
  • def
  • in
  • trait

Multi-methods

在Groovy中,将在运行时选择将被调用的方法。 这称为运行时分派或Multi-methods。 这意味着将基于运行时参数的类型来选择方法。 在Java中,则是根据声明的类型,在编译时选择方法。

下面的代码,以Java代码编写,可以在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版本。

==的行为

在Java中==表示对象的原始类型或标识的相等性。 在Groovy ==翻译为a.compareTo(b)== 0,如果他们是可比较的,否则a.equals(b)。 如果要检查身份,有is方法,例如a.is(b)

数组初始化

在Groovy中,{...}块是为闭包而保留的。 这意味着您不能使用以下语法创建数组literal

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

实际上你必须使用:
 

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

GStrings

由于双引号字符串字面量被解释为GString,如果具有包含美元字符的String的类是使用Groovy和Java编译器编译的,Groovy可能会失败并产生编译错误或产生细微不同的代码。

通常,Groovy将在GStringString之间自动转换,如果API声明参数的类型,小心接受Object参数的Java API,然后检查实际的类型。

原始和封装

因为Groovy使用Objects来做每一件事,它对原始的引用自动包装。 因此,它不遵循Java的行为扩展优先于装箱。 这里有一个使用int的例子。

int i
m(i)

//这是Java将调用的方法,因为扩展优先于拆箱。
void m(long l) {
  println "in m(long)"
}

//这是Groovy实际调用的方法,因为所有的基本引用都使用它们的包装类。
void m(Integer i) {
  println "in m(Integer)"
}

包范围可见性

在Groovy中,在字段上省略修饰符不会像Java中一样变成package-private字段:

class Person {
     字符串名称
}}

相反,它用于创建一个属性,也就是说一个私有字段,一个关联的getter和一个关联的setter

可以通过使用@PackageScope注释来创建一个package-private字段:

class Person {
     @PackageScope字符串名称
}}

内部类

匿名内部类和嵌套类的实现遵循Java方式,但是你不应该拿出Java语言规范,并且对不同的东西不断地摇头。 它的实现看起来很像groovy.lang.Closure,同时有一些好处和一些差异。 例如访问私有字段和方法可能成为一个问题,但另一方面,局部变量不必是final的。

  1. 静态内部类
    这里有一个静态内部类的例子:
    class A {
        static class B {}
    }
    
    new A.B()

    静态内部类的使用是最好的支持。 如果你需要一个内部类,你最好使用静态的。

  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)

  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)。 由于这也可能是正常的方式,目前还没有一个好的方法来防止这个问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值