在Scala中,对于脚本文件,其扩展名为.sc
,而编译后的文件扩展名为.scala
。
通常对于脚本文件,使用scala环境,然后使用:load命令加载(编译并运行)文件:
# upper1.sc
class Upper{
def upper(strings: String*): Seq[String] = {
strings.map((s:String) => s.toUpperCase())
}
}
val up = new Upper
println(up.upper("Hello", "World!"))
scala> :load upper1.sc
Loading upper1.sc...
defined class Upper
up: Upper = Upper@38fb151a
ArrayBuffer(HELLO, WORLD!)
上述脚本中,只有最后一行才是println命令的输出,其他行则是REPL提供的一些反馈信息。
假如的确希望能将脚本文件编译为JVM的字节码(一组.class文件),可以在scalac命令中传入-Xscript参数,表示你所选中的main类,它是生成的Java应用程序的入口点。
PS C:\Users\yilon\hello> scalac -Xscript Upper1 upper1.sc
上述命令中,第一行命令生成一连串的字节码文件,并最终生成Upper1.class文件
-a---- 2018/1/3 18:13 2297 Upper1$$anon$1$Upper.class
-a---- 2018/1/3 18:13 1024 Upper1$$anon$1.class
-a---- 2018/1/3 18:13 598 Upper1$.class
-a---- 2018/1/3 18:13 580 Upper1.class
再通过scala执行该Upper1字节码文件,得到最终输出结果。
PS C:\Users\yilon\hello> scala Upper1
ArrayBuffer(HELLO, WORLD!)
Upper1.class中包含了可执行的主程序,可以使用javap和Scala对应工具scalap,对该文件实施逆向工程!
PS C:\Users\yilon\hello> javap -cp . Upper1
Compiled from "upper1.sc"
public final class Upper1 {
public static void main(java.lang.String[]);
}
PS C:\Users\yilon\hello> scalap -cp . Upper1
object Upper1 extends scala.AnyRef {
def this() = { /* compiled code */ }
def main(args: scala.Array[scala.Predef.String]): scala.Unit = { /* compiled code */ }
}
我们对最初upper1.sc脚本文件进行一次重构,把这个脚本文件转化成编译好的一个命令行工具。也就是说,我们将创建一个包含了main方法的更为经典的JVM应用程序。
# upper1.scala
object Upper{
def main(args:Array[String]) = {
args.map(_.toUpperCase()).foreach(printf("%s ",_))
println("")
}
}
如果代码具有.scala扩展名,那就表示我们会使用scalac编译它。现在upper方法被改名成了main方法。由于Upper是一个对象,main方法就像是Java类的静态main方法一样。它就是Upper应用的入口点。
在Scala中,main方法必须为对象方法。(在Java中,main方法必须是类静态方法。)应用程序的命令参数将作为一组字符串传递给main方法。举例来说,输入参数是args:Array[String]。
为了运行代码,必须首先实用scalac,将代码编译成为一个能在JVM下运行的.class文件
PS C:\Users\yilon\hello> scalac upper1.scala
得到两个字节码文件:
-a---- 2018/1/3 18:32 3023 Upper$.class
-a---- 2018/1/3 18:32 578 Upper.class
输入任意长度的字符串参数并执行命令
PS C:\Users\yilon\hello> scala -cp . Upper Hello World
HELLO WORLD
通过选项-cp .
将当前目录添加到查询类路径中(classpath)中,不过在这里其实并不需要该选项。
由于SBT会帮助我们编译文件,我们实际上并不需要手动编译这些文件,在SBT提示符下,我们可以使用下列命令运行程序
PS C:\Users\yilon\hello> sbt
"C:\Users\yilon\.sbt\preloaded\org.scala-sbt\sbt\"1.0.4"\jars\sbt.jar"
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[warn] No sbt.version set in project/build.properties, base directory: C:\Users\yilon\hello
[info] Loading settings from idea.sbt ...
[info] Loading global plugins from C:\Users\yilon\.sbt\1.0\plugins
[info] Set current project to hello (in build file:/C:/Users/yilon/hello/)
[info] sbt server started at 127.0.0.1:5736
sbt:hello> runMain Upper Hello World
[info] Compiling 3 Scala sources to C:\Users\yilon\hello\target\scala-2.12\classes ...
[info] Done compiling.
[warn] Multiple main classes detected. Run 'show discoveredMainClasses' to see the list
[info] Packaging C:\Users\yilon\hello\target\scala-2.12\hello_2.12-0.1-SNAPSHOT.jar ...
[info] Done packaging.
[info] Running Upper Hello World
HELLO WORLD
[success] Total time: 5 s, completed 2018-1-3 18:47:41
在上述命令消息队列中,显示了编译文件的存储路径[info] Compiling 3 Scala sources to C:\Users\yilon\hello\target\scala-2.12\classes ...
,可以通过scala命令来执行
PS C:\Users\yilon\hello> scala -cp target\scala-2.12\classes Upper Hello World
HELLO WORLD
概括的说,假如在命令行输入scala命令时不指定文件参数,REPL将启动。在REPL中输入命令、表达式和语句都会被直接执行。假如输入scala命令时指定Scala源文件,scala命令将会以脚本的形式编译并运行文件。另外,假如你提供了JAR文件或是一个定义了main方法的类文件,scala会像Java命令那样执行该文件。
参考文献:[1]. Scala程序设计(第二版)
转载请注明出处:http://blog.csdn.net/coder__cs/article/details/78992764
本文出自【elon33的博客】