groovy对象和原始混淆

时间:2014-02-06 17:09:42

标签: groovy

这是(groovy)类的一部分,它将一些数据存储在Mongodb中:

long save(Object data) {

    def customerReference = getNextCustomerReference()

    def map = ['customerReference': customerReference, 'data': data, 'created': new Date()]

    BasicDBObject basicDBObject = new BasicDBObject(map)
    collection.insert(basicDBObject)
    customerReference
}

private long getNextCustomerReference() {
    1234
}

即使我已明确表示我想要一个原始的long,但最终在数据库中的是一个对象:

{ "_id" : ObjectId("52f3c0597d844b0fcee29013"), "customerReference" : NumberLong(1234), "data" : "original data", "created" : ISODate("2014-02-06T17:03:21.411Z") }

但是,如果我将私有方法的返回类型更改为def,则会发生这种情况:

{ "_id" : ObjectId("52f3c1477d84698725f50fe5"), "customerReference" : 1234, "data" : "data", "created" : ISODate("2014-02-06T17:07:19.055Z") }

我想要的行为(存储在数据库中的原语)。

有人可以解释这一点,因为它令人费解。当然,如果我不知道如何定义类型,Groovy应该尝试尊重它吗?

1 个答案:

答案 0 :(得分:2)

Groovy几乎总是自动将原始类型自动装箱到它们的数字引用类型 - 等价:

long test_long() { 123l }
int test_int() { 123 }
def test_def() { 123 }
def test_def_long() { 123l }

long l = 42l

assert test_long().class == Long.class
assert test_int().class == Integer.class
assert test_def().class == Integer.class
assert test_def_long().class == Long.class
assert l.class === Long.class

如果删除long返回类型,则会将对象自动装箱到java.lang.Integer。看起来你的代码处理Integer就像一个“原始”。

前段时间Groovy 1.8 introduced primitive type optimization,在某些情况下使用原始类型的内部回退。这在某些情况下会有所帮助,但是内部性能优化是您无法直接使用的(通过使用某些语法结构或类似的东西)。

有时你可以通过显式强制转换来强制原语,但是很有可能它会在方法调用和东西的过程中被转换为引用类型。