使用 def 和不使用 def 定义变量有什么区别?

What is the difference between defining variables using def and without?

关于 Jenkins DSL,有什么区别:

def cwd = pwd()

cwd = pwd()

?

这是个好问题,但更像是一个 Groovy 问题。

据我所知,定义一个没有 def 关键字的变量将在脚本中起作用,但如果您在 class 方法中则不行。来自这个 blog post 的示例:

class MyTest {
    def testMethod() {
        y = 3
        println y
    }    
}

t = new MyTest()
t.testMethod()

变量 t 的定义没有问题,但 y 的定义会抛出异常。

这意味着在我们的上下文(Jenkins 管道)中,您始终可以在不使用 def 关键字的情况下定义变量,因为您始终处于脚本上下文中,并且您的变量将绑定到脚本。但是,我认为使用 def 关键字是一种很好的做法,因为它表明您知道何时实例化变量,并且还可以避免一些重复变量定义的问题(如果您使用 def如果你定义同一个变量两次,至少关键字编译会失败。

最后,来自Groovy documentation :

When using def in Groovy, the actual type holder is Object (so you can assign any object to variables defined with def, and return any kind of object if a method is declared returning def).

所以您可能想要具体并指定您正在定义的变量类型。在您的情况下,您可以将 cwd 定义为:

String cwd = pwd()

它会禁止你做这样的事情:

def cwd = pwd()
cwd = 1000     // Valid code

String cwd2 = pwd()
cwd2 = 1000    // Will fail compilation

这是范围的不同。当您为没有 "def" 或其他类型的变量赋值时,在 Groovy 脚本中,它被添加到 "binding",脚本的全局变量。这意味着它可以从脚本中的所有函数访问。这很像您在脚本顶部定义了变量。

如果多个线程对脚本进行操作,您可能会出现意外行为。

def a = {
  x = 1
  println x
}
def b = {
  x = 2
  println x
}
new Thread(a).start()
new Thread(b).start()

...可以产生两个,两个两个,或者混合。

相比之下,使用"def"使局部变量:

def a = {
  def x = 1
  println x
}
def b = {
  def x = 2
  println x
}
new Thread(a).start()
new Thread(b).start()

... 将始终以任意顺序打印 1 和 2。