美文网首页
Groovy学习(一)——脚本与类

Groovy学习(一)——脚本与类

作者: 山中散仙 | 来源:发表于2020-09-22 16:10 被阅读0次

脚本与类

Groovy代码文件与class文件的对应关系
作为基于JVM的语言,Groovy可以非常容易的和Java进行互操作,但也需要编译成class文件后才能运行,所以了解Groovy代码文件和class文件的对应关系,有助于更好地理解Groovy的运行方式和结构。

对于没有任何类定义

如果Groovy脚本文件里只有执行代码,没有定义任何类(class),则编译器会生成一个Script的子类,类名和脚本文件的文件名一样,而脚本的代码会被包含在一个名为run的方法中,同时还会生成一个main方法,作为整个脚本的入口。

对于仅有一个类

如果Groovy脚本文件里仅含有一个类,而这个类的名字又和脚本文件的名字一致,这种情况下就和Java是一样的,即生成与所定义的类一致的class文件, Groovy类都会实现groovy.lang.GroovyObject接口。

对于多个类

如果Groovy脚本文件含有一个或多个类,groovy编译器会很乐意地为每个类生成一个对应的class文件。如果想直接执行这个脚本,则脚本里的第一个类必须有一个static的main方法。

对于有定义类的脚本

如果Groovy脚本文件有执行代码, 并且有定义类, 那么所定义的类会生成对应的class文件, 同时, 脚本本身也会被编译成一个Script的子类,类名和脚本文件的文件名一样

1. public static void main vs script

Groovy 同时支持脚本和类。以以下代码为例:

Main.groovy

class Main {                                       
    static void main(String... args) {     
        println 'Groovy world!'                   
    }
}

定义类,名称是Main
main方法用作类的主要方法 public static void main(String[])
方法的主体println 'Groovy world!'
这是典型的java代码,其中代码必须嵌入到一个类中方可执行。Groovy 使它更简洁:
Main.groovy
println 'Groovy world!'
脚本可以被视为类,无需声明它,但存在一些差异。

2. 脚本转换为类

脚本始终会被编译为类。Groovy 编译器将为你编译该类,并将脚本的正文复制到方法中。因此,前面的示例的编译情况类似如下:
Main.groovy

import org.codehaus.groovy.runtime.InvokerHelper
class Main extends Script {                     
    def run() {                                 
        println 'Groovy world!'                 
    }
    static void main(String[] args) {           
        InvokerHelper.runScript(Main, args)     
    }
}

类继承自 groovy.lang.Script
groovy.lang.Script需要一个带返回值的方法run

image.png

脚本正文进入方法run
该方法是自动生成的main
并委托对方法执行脚本run
如果脚本位于文件中,则该文件的基名用于确定生成的脚本类的名称

3.方法

可以定义方法到脚本中,如下所示

int fib(int n) {
    n < 2 ? 1 : fib(n-1) + fib(n-2)
}
assert fib(10)==89s

您还可以混合方法和代码。生成的脚本类将所有方法都引入脚本类,并将所有脚本体组合到方法中:

//脚本开始
println 'Hello'                                 
//在脚本正文中定义方法
int power(int n) { 2**n }                       
//脚本继续
println "2^6==${power(6)}"  

此代码在内部转换为:

import org.codehaus.groovy.runtime.InvokerHelper
class Main extends Script {
    int power(int n) { 2** n}                   
    def run() {
        println 'Hello'                         
        println "2^6==${power(6)}"              
    }
    static void main(String[] args) {
        InvokerHelper.runScript(Main, args)
    }
}

4.变量

脚本中的变量不需要类型定义。这意味着此脚本:

int x = 1
int y = 2
assert x+y == 3

行为与以下行为相同:

x = 1
y = 2
assert x+y == 3

但是,两者之间存在语义差异:

如果变量声明为第一个示例中,则它是局部变量。它将在编译器生成的方法run中声明,并且在脚本主体之外不可见。特别是此变量在脚本的其他方法中不可见

如果变量未声明类型或def占位符,则进入脚本绑定。绑定从方法中可见,如果使用脚本与应用程序交互,并且需要在脚本和应用程序之间共享数据,则绑定尤其重要。

如果希望变量成为类的字段而不进入Binding ,可以使用@Field注释

相关文章

网友评论

      本文标题:Groovy学习(一)——脚本与类

      本文链接:https://www.haomeiwen.com/subject/mdmwyktx.html