Java & Groovy & Scala & Kotlin - 10.脚本

Overview

本节主要介绍各语言中脚本的实现和运行方式。所谓的脚本是使用一种特定的描述性语言,依据一定的格式编写的可执行文件。通常可以用于执行一些简单的代码。

Java 篇

Java 并不支持脚本

Groovy 篇

Groovy 中脚本后缀名也是 .groovy

创建第一个脚本

新建文件 scriptTest.groovy,文件内容如下

println("Hello World")

保存文件后在控制台 中执行以下语句

groovy scriptTest.groovy

成功的话可以看到命令行输出 Hello World 字符串。这就是脚本的优点,无需创建类,也无需编写可以 main() 方法就可以直接运行代码。

在类或脚本中执行脚本

Groovy 脚本在编译后实际也会转变为对应的 Java 类,所以上一节的例子在编译后会变成以下的代码

public class scriptTest extends Script {
    public scriptTest() {
        CallSite[] var1 = $getCallSiteArray();
    }

    public scriptTest(Binding context) {
        CallSite[] var2 = $getCallSiteArray();
        super(context);
    }

    public static void main(String... args) {
        CallSite[] var1 = $getCallSiteArray();
        var1[0].call(InvokerHelper.class, scriptTest.class, args);
    }

    public Object run() {
        CallSite[] var1 = $getCallSiteArray();
        return var1[1].callCurrent(this, "Hello World");
    }
}

分析以上代码,可以看到 Groovy 脚本编译后实际是生成了一个继承自 Script 的类。该类有两个构造方法(空构造方法和以 Binding 为参数的构造方法),一个 main() 方法,一个 run() 方法,实际编写的代码其实是被编译到 run() 方法中。所以在其它程序中执行 Groovy 脚本就很容易了,只要 new 一个这个脚本类的实例并执行 run() 方法就可以了。

def scope = new scopeScript()
scope.run()

这里特别要注意的是 Groovy 脚本名可以包含 - 这样的特殊字符,但是这种字符并不符合 Java 的类名规范,所以如果脚本名包含特殊字符时就无法通过以上方被执行代码,所以最简单的避免方式就是脚本名不要用特殊字符。

本地域与绑定域

Groovy 脚本中定义的变量有两种作用域,分别为绑定域 (Binding Scope) 和本地域 (Local Scope)。本地域为脚本中使用 def 定义的动态类型变量或用特定类型定义的静态类型变量。绑定域为没有任何前缀修改的变量。

本地域

String hello = "hello"
def world = "world"

绑定域

helloworld = "hello world"

本地域在编译后会被声明为 run() 方法中的临时变量,所以只能被脚本当中的语句调用,无法被脚本中定义的其它方法调用。

绑定域可以通过外部的脚本对象的 binding 属性进行赋值,在编译后会被变为脚本类的成员变量,所以可以被脚本中定义的其它方法调用。

编写 scopeScript.groovy 文件,内容如下

package com.bookislife.jgsk.groovy._10_script

//local scope
String hello = "hello"
def world = "world"

//binding scope
helloworld = "hello world"

void otherMethod() {
    //  Wrong!! 无法访问本地域 hello 和 world
//    println hello
//    println world
    // 可以访问绑定域
    println(helloworld)
}

println "${hello} ${world}, ${helloworld}"

//  脚本中定义的方法只能访问绑定域
otherMethod()

编写 Scripts.groovy 类文件,以此来调用 scopeScript.groovy 文件

package com.bookislife.jgsk.groovy._10_script

class Scripts {

    public static void main(String[] args) {
        //  Run Scripts
        def scope = new scopeScript()

        //  Binding Values
        scope.binding.hello = "goodbye"       //    hello is not a binding scope
        scope.binding.helloworld = "hello groovy"   //  helloworld is a binding scope
        scope.otherMethod()
    }
}

通过以上代码可以看到可以使用 binding 属性为脚本中的绑定域进行赋值,但是无法修改本地域。

Scala 篇

Scala 脚本不会被编译成类文件,所以没有 Groovy 脚本那么强大的功能。

编写脚本

编写脚本文件 scriptTest.scala

println(s"Hello World, ${if (args.nonEmpty) args(0) else ""}")

保存文件,在控制台下执行以下代码

scala scriptTest.scala Peter

成功的话会输出 "Hello World, Peter"。

从以上代码可以看到 Scala 脚本中使用默认的数组 args 来存储输入的参数。

在 IDEA 中运行脚本

和 Groovy 不一样,Scala 脚本无法直接在 IDEA 中运行,IDEA 会报无法执行或者运行时报找不到符号。如果希望在 IDEA 中运行的话,需要先进行以下设置:

  1. 打开 "Run" -> "Edit Configurations"
  2. 点击左上角的 "+" 号,选择 "Scala Script"
  3. 输入任意 Name,在 "Script file" 一项中选择要运行的脚本文件
  4. 在 "Before launch" 一项中删除 "Make" 操作
  5. 上述完成后就可以运行脚本了


Kotlin 篇

Kotlin 脚本后缀为 .kts,是 Kotlin 1.0 新增加的功能。

编写脚本

编写脚本文件,scriptTest.kts,内容如下

println("Hello World, ${if (args.isNotEmpty()) args[0] else ""}")

保存后在命令行执行以下代码

kotlinc -script scriptTest.kts Peter

成功的话会输出 "Hello World, Peter"。

同 Scala 一样,Kotlin 脚本也使用数组 args 来存储输入的参数。

Summary

  • 除 Java 外都支持脚本,其中 Groovy 的功能最强
  • Idea 可以直接运行 Groovy 和 Kotlin 脚本,但不支持直接运行 Scala 脚本

文章源码见 https://github.com/SidneyXu/JGSK 仓库的 _10_script 小节

你可能感兴趣的:(Java & Groovy & Scala & Kotlin - 10.脚本)