def
关键字来前缀赋值操作?def x = 0
def y = 5
while ( y-- > 0 ) {
println "" + x + " " + y
x++
}
assert x == 5
def
关键字可以被移除,该代码片段将产生相同的结果。那么def
关键字的作用是什么?
def
关键字来前缀赋值操作?def x = 0
def y = 5
while ( y-- > 0 ) {
println "" + x + " " + y
x++
}
assert x == 5
def
关键字可以被移除,该代码片段将产生相同的结果。那么def
关键字的作用是什么?
这是基本脚本的语法糖。省略 "def" 关键字会将变量放入当前脚本的绑定中,并且 Groovy 将其(大多数情况下)视为全局作用域变量:
x = 1
assert x == 1
assert this.binding.getVariable("x") == 1
使用def关键字而不是其他关键字,不会将变量放入脚本绑定中:
def y = 2
assert y == 2
try {
this.binding.getVariable("y")
} catch (groovy.lang.MissingPropertyException e) {
println "error caught"
}
输出:"捕获错误"
在更大的程序中使用def关键字很重要,因为它有助于定义变量可以被找到的范围,可以帮助保护封装。
如果您在脚本中定义了一个方法,它将无法访问在主脚本体中用"def"创建的变量,因为它们不在范围内:
x = 1
def y = 2
public bar() {
assert x == 1
try {
assert y == 2
} catch (groovy.lang.MissingPropertyException e) {
println "error caught"
}
}
bar()
打印“捕获到错误”
函数内没有“y”变量的范围。 “x”在范围内,因为Groovy将检查当前脚本的绑定变量。正如我之前所说,这只是一种语法糖,可以更快地键入快速且不太规范的脚本(通常是一行代码)。
在较大的脚本中的良好实践是始终使用“def”关键字,以避免遇到奇怪的作用域问题或干扰您不想要的变量。
正如Ben所说,将其视为“Object”——但更酷的是它不会限制您使用Object的方法。这对于导入具有独特的意义。
例如,在此片段中,我必须导入FileChannel:
// Groovy imports java.io.* and java.util.* automatically
// but not java.nio.*
import java.nio.channels.*
class Foo {
public void bar() {
FileChannel channel = new FileInputStream('Test.groovy').getChannel()
println channel.toString()
}
}
new Foo().bar()
例如,只要所有内容都在类路径上,我就可以随意处理它。
// Groovy imports java.io.* and java.util.* automatically
// but not java.nio.*
class Foo {
public void bar() {
def channel = new FileInputStream('Test.groovy').getChannel()
println channel.toString()
}
}
new Foo().bar()
就这个单独的脚本而言,实际上没有什么区别。
然而,使用关键字“def”定义的变量被视为局部变量,即仅限于此脚本。没有在它们前面加上“def”的变量在第一次使用时存储在所谓的绑定中。您可以将绑定视为变量和闭包的通用存储区,这些变量和闭包需要在“脚本之间”可用。
因此,如果您有两个脚本并使用相同的GroovyShell执行它们,则第二个脚本将能够获取在第一个脚本中设置的所有没有“def”的变量。
bill = 7
bi1l = bill + 3
assert bill == 7
实际上,我认为它不会表现得一样...
Groovy中的变量仍然需要声明,只是不需要类型声明,因为右侧通常包含足够的信息供Groovy对变量进行类型推断。
当我尝试使用未使用def或类型声明的变量时,会出现“无此属性”的错误,因为它假定我正在使用包含代码的类的成员。
new FileInputStream('Test.groovy').getChannel()
? - Alexander Suraphel