5.4 Scala语法和规则
Scala不像Java那样严格而繁琐:分号是可选的;在不必要的情况下,函数调用中的小括号也并非必不可少的(请看前述示例中的代码行val b = new AddDemoFunctional)。本节介绍如下主题:
- 静态类型语言;
- 可修改的变量和不可修改的变量;
- 常用的Scala类型。
5.4.1 静态类型语言
与Java一样,Scala也是一种静态类型语言:使用变量前必须先声明。Scala也是一种强类型语言:你总是可以指定要使用的类型,就像在Java代码中一样;但与Java不同的是,并非必须显式地指定类型。
声明方法的输入参数和返回值时,必须指定类型,但在方法或函数中声明变量时,并非必须指定类型,因为Scala编译器通常能够根据代码推断出变量的正确类型。
下面是一个这样的示例:
var i = 10;var j = new java.lang.Object();
声明可修改的变量后,就可使用它来存储指定类型或可向上转换为该类型的值。例如,可在上述代码后面编写如下代码:
j = "Hello world"
由于String类型可向上转换为java.lang.Object,因此可使用变量j来存储指向字符串"Hello world"的引用。但不能将String赋给变量i,因为你将一个Int实例赋给了这个变量,String不能向上转换为Int实例。
可显式地指定变量的类型;使用类系列时,可能必须提供这种信息:
val i: Integer = 10
5.4.2 可修改的变量和不可修改的变量
Scala支持两种变量。声明方法的参数或类的实例成员时,必须使用下面两个关键字之一。
var:用于声明可修改的变量;val:用于声明固定变量。
可修改的变量相当于Java中的普通变量,它们是可修改的,可随便修改;固定变量相当于Java中的final变量,只能给它们赋值一次。如果固定变量指向一个可修改的类实例,你依然可以修改这个实例的内容,这在第2章讨论过。
进行函数式编程时,应尽可能使用不可修改的变量。不可修改的值是函数式编程的基石。
Scala不支持静态变量(也叫类变量),但正如后面将介绍的,它支持可用于替代静态变量的单例对象。
5.4.3 常用的Scala类型
在Scala中,可使用常见的Java类,但Scala也提供了自己的类,你应尽可能使用这些类。这些类的工作原理带有Scala的烙印,这里介绍其中的如下几个:
Any;AnyRef;AnyVal;字符串。
Any类
在Java中,祖先类为Object,而在Scala中,祖先类为Any,因此在没有显式指定时,所有的类都隐式地继承Any类。

如上图所示,Any类有两个子类:
AnyRef;AnyVal。
(1)AnyRef类——引用类
AnyRef类由引用变量使用,类似于Java类java.lang.Object,提供的方法也类似,如equals()、hashCode()和finalize()。Scala中的大部分类都直接或间接地继承了AnyRef类。
(2) AnyVal类——值类
不同于Java,Scala是一种纯粹的面向对象语言,因此不支持基本类型值,而是将它们封装在包装类中:

这些包装类都是AnyVal的子类,它们被称为值类,Scala编译器以特殊的方式处理它们。
你可能会问,Scala为何使用自己的包装类,而不使用Java类库中的包装类。一个原因是Scala力图通过避免不必要的装箱来改善性能,为此需要有自己的内部逻辑;另一个重要的原因是Scala支持运算符重载(这不同于Java)。Scala包装类实现了用于计算的所有二元运算符,稍后将更详细地讨论这一点。
- 字符串
很多JVM语言都提供了自己的字符串类,这些类除了Java标准类String的方法和字段外,还提供了其他的便利方法和字段,但Scala不是这样的,它使用Java类库中java.lang包中的String类。
Java字符串是不可修改的。如果方法要修改字符串,它将返回一个新的String实例,其中包含修改后的字符串,而原来的String实例保持不变。这种不变性正是Scala的函数式编程功能所需要的。
