【问题标题】:groovy Object and primitive confusiongroovy 对象和原始混淆
【发布时间】:2014-02-06 17:09:41
【问题描述】:

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

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 应该尝试并尊重它吗?

【问题讨论】:

  • 如果你这样做long customerReference = getNextCustomerReference()怎么办?
  • 作为对象进入。更奇怪的是,如果我这样做并在方法 def 上设置返回类型,它会作为一个对象进入。
  • 如果你跳过BasicDBObject 直接去collection.insert( map ) 怎么办?我认为这是允许的
  • (假设您使用的是 GMongo)
  • 我没有使用任何第三方映射工具,并且在这个阶段我不想使用。无论如何,这个问题更多是关于 Groovy 而不是 Mongodb。

标签: groovy


【解决方案1】:

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,在某些情况下使用原始类型的内部回退。这在某些情况下会有所帮助,但它是您无法直接使用的内部性能优化(通过使用某种语法结构或类似的东西)。

有时您可以通过显式强制转换来强制使用原语,但很有可能它会通过方法调用和其他东西被转换为引用类型。

【讨论】:

    猜你喜欢
    • 2013-03-30
    • 2017-01-23
    • 2014-07-02
    • 2014-06-03
    • 1970-01-01
    • 1970-01-01
    • 2010-11-30
    • 2012-07-30
    相关资源
    最近更新 更多