Groovy:定义没有“def”的变量和使用锚定之间有什么区别?

时间:2016-11-10 13:25:19

标签: groovy scope

我现在正在学习Groovy,而且我碰到了一些我不理解的东西,我希望你能够解决一些问题。

关于以下示例:

import groovy.transform.Field
  @Field List awe = [1, 2, 3]
  def awesum() { awe.sum() }
  assert awesum() == 6

据我所知,这种锚定允许我将awe变量的范围从在脚本的方法级别运行到脚本的类级别。

但是后来我想到用def或没有定义变量之间的区别,例如:

def var = "foo"

var = "foo"

据我所知,两个例子之间的区别在于范围的差异。 当我为没有“def”或其他类型的变量赋值时,在Groovy脚本中,它被添加到“绑定”,即脚本的全局变量。 这意味着可以从脚本中的所有功能访问它。

因此,考虑到“@Field”和定义变量而不使用“def”并遵循这一思路我已将示例代码更改为:

import groovy.transform.Field
  awe = [1, 2, 3]
  def awesum() { awe.sum() }
  assert awesum() == 6

它有效。

所以我的问题是为什么要使用锚定?如果你可以通过定义一个没有“def”的变量来实现相同的目标吗?

3 个答案:

答案 0 :(得分:3)

没有实现相同的目标 - 请参阅下面的区别

import groovy.transform.Field
awe = [1, 2, 3]
def awesum() { awe.sum() }
assert awesum() == 6
awe = 1

工作正常,因为变量是动态类型的。 相反,这失败了

import groovy.transform.Field
@Field List awe = [1, 2, 3]
def awesum() { awe.sum() }
assert awesum() == 6
awe = 1

由于变量是强类型的(java.util.ArrayList)

Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '1' with class 'java.lang.Integer' to class 'java.util.List'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '1' with class 'java.lang.Integer' to class 'java.util.List'
        at FieldTest1.run(FieldTest1.groovy:5)

答案 1 :(得分:3)

@Field比脚本更年轻,其目的是让open块具有附加状态的能力。如果你对绑定感到满意,那么就没有太大的理由让它与众不同。如果你需要绑定中的值,那么@Field是无可替代的。另一方面,如果绑定必须只包含某些变量,则@Field可以成为必须

预期用途示例:

def cl = {
  Field x = 1
  x++
}

在这个例子中,open block cl有一个字段x,脚本在绑定中没有x,也没有局部变量x。但是,当创建开放块时,赋值x = 1仅执行一次。但您仍可以通过该字段上的操作更改值。这样每次调用cl()都会产生一个新值,从1开始。

答案 2 :(得分:0)

在没有“ def”的类或方法中定义变量会产生语法错误。像这样:

class Cat {
    def name = "Amy"
    nickname = "Lisa" // Error

    def greet() {
        tmp = "" // Error
        println "I am $name"
    }
}

在Groovy脚本中定义不带“ def”的变量会使它在某种程度上成为全局变量。像这样:

name = "Amy" // Global variable, giving errors if "def" is added

def greet() {
    println "I am $name"
}

greet()