全部博文(465)
分类: Java
2012-10-29 15:07:46
Scala解释器
启动Scala解释器的步骤如下:
●安装Scala。
●确保scala/bin目录位于系统PATH中。
●在你的操作系统中打开命令行窗口。
●键入scala并按Enter键。
提示:不喜欢命令行?你也可以通过其他方式运行Scala解释器,参见 。
现在,键入命令,然后按Enter键。每一次,解释器都会显示出结果。例如,当你键入“8 * 5 + 2”(如下面加粗的文字),将得到42。
scala> 8 * 5 + 2
res0: Int = 42
答案被命名为res0,你可以在后续操作中使用这个名称:
scala> 0.5 * res0
res1: Double = 21.0
scala> "Hello," + res0
res2: java.lang.String = Hello, 42
正如你所看到的,解释器同时还会显示结果的类型——拿本例来说就是Int、Double和java.lang.String。
你可以调用方法。根据启动解释器的方式的不同,你可能可以使用Tab键补全而不用完整地手工键入方法名。你可以试着键入res2.to,然后按Tab键,如果解释器给出了如下选项:
toCharArray toLowerCase toString toUpperCase
说明Tab键补全功能是好的。接下来键入U并再次按Tab键,你应该就能定位到单条补全如下:
res2.toUpperCase
按下Enter键,结果就会被显示出来。(如果在你的环境中无法使用Tab键补全,那你就只好自行键入完整的方法名了。)
同样地,可以试试按↑和↓方向键。在大多数实现当中,你将看到之前提交过的命令,并且可以进行编辑。用←、→和Del键将上一条命令修改为:
res2.toLowerCase
正如你所看到的,Scala解释器读到一个表达式,对它进行求值,将它打印出来,接着再继续读下一个表达式。这个过程被称做读取-求值-打印-循环,即REPL。
从技术上讲,scala程序并不是一个解释器。实际发生的是,你输入的内容被快速地编译成字节码,然后这段字节码交由Java虚拟机执行。正因如此,大多数Scala程序员更倾向于将它称做“REPL”。
提示:REPL是你的朋友。即时反馈鼓励我们尝试新的东西;而且,如果它跑出你想要的效果,你会很有成就感。
同时,打开一个编辑器窗口也是个不错的主意,这样你就可以将成功运行的代码片段复制、粘贴出来供今后使用。同样地,当你尝试更复杂的示例时,你也许会想要在编辑器中组织好以后再贴到REPL。
声明值和变量
除了直接使用res0、res1等这些名称之外,你也可以定义自己的名称:
scala> val answer = 8 * 5 + 2
answer: Int = 42
你可以在后续表达式中使用这些名称:
scala> 0.5 * answer
res3: Double = 21.0
以val定义的值实际上是一个常量——你无法改变它的内容:
scala> answer = 0
如果要声明其值可变的变量,可以用var:
var counter = 0
counter = 1 // OK,我们可以改变一个var
在Scala中,我们鼓励你使用val——除非你真的需要改变它的内容。Java或C++程序员也许会感到有些意外的是,大多数程序并不需要那么多var变量。
注意,你不需要给出值或者变量的类型,这个信息可以从你用来初始化它的表达式推断出来。(声明值或变量但不做初始化会报错。)
不过,在必要的时候,你也可以指定类型。例如:
val greeting: String = null
val greeting: Any = "Hello"
说明:在Scala中,变量或函数的类型总是写在变量或函数名称的后面。这使得我们更容易阅读那些复杂类型的声明。
当我在Scala和Java之间来回切换的时候,我发现我经常无意识地敲出Java方式的声明,比如String greeting,需要手工改成greeting: String。这有些烦人,但每当我面对复杂的Scala程序时,我都会心存感激,因为我不需要再去解读那些C风格的类型声明。
说明:你可能已经注意到,在变量声明或赋值语句之后,我们并没有使用分号。在Scala中,仅当同一行代码中存在多条语句时才需要用分号隔开。
你可以将多个值或变量放在一起声明:
val xmax, ymax = 100 // 将xmax和ymax设为100
var greeting, message: String = null
// greeting和message都是字符串,被初始化为null
常用类型
到目前为止你已经看到过Scala数据类型中的一些,比如Int和Double。和Java一样,Scala也有7种数值类型:Byte、Char、Short、Int、Long、Float和Double,以及1个Boolean类型。跟Java不同的是,这些类型是类。Scala并不刻意区分基本类型和引用类型。你可以对数字执行方法,例如:
1.toString() // 产出字符串"1"
或者,更有意思的是,你可以:
1.to(10) // 产出Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
(我们将在第13章介绍Range类,现在你只需要把它当做一组数字就好。)
在Scala中,我们不需要包装类型。在基本类型和包装类型之间的转换是Scala编译器的工作。举例来说,如果你创建一个Int的数组,最终在虚拟机中得到的是一个int[]数组。
正如你在1.1节中看到的那样,Scala用底层的java.lang.String类来表示字符串。不过,它通过StringOps类给字符串追加了上百种操作。
举例来说,intersect方法输出两个字符串共通的一组字符:
"Hello".intersect("World") // 输出"lo"
在这个表达式中,java.lang.String对象"Hello"被隐式地转换成了一个StringOps对象,接着StringOps类的intersect方法被应用。
因此,在使用Scala文档的时候,记得要看一下StringOps类。
同样地,Scala还提供了RichInt、RichDouble、RichChar等。它们分别提供了它们可怜的堂兄弟们——Int、Double、Char等——所不具备的便捷方法。我们前面用到的to方法事实上就是RichInt类中的方法。在表达式
1.to(10)
中,Int值1首先被转换成RichInt,然后再应用to方法。
最后,还有BigInt和BigDecimal类,用于任意大小(但有穷)的数字。这些类背后分别对应的是java.math.BigInteger和java.math.BigDecimal,不过,在1.4节你会看到,它们用起来更加方便,你可以用常规的数学操作符来操作它们。
说明:在Scala中,我们用方法,而不是强制类型转换,来做数值类型之间的转换。举例来说,99.44.toInt得到99,99.toChar得到'c'。当然,和Java一样,toString将任意的对象转换成字符串。
要将包含了数字的字符串转换成数值,使用toInt或toDouble。例如,"99.44".toDouble得到99.44。
本文节选自《快学Scala》
电子工业出版社出版
(美)霍斯曼(Horstmann,C.S.)著
高宇翔译