1、 前言
从技术上讲,scala程序并不是一个解释器。实际发生的是,输入的内容被快速地编译成字节码,然后这段字节码交由java虚拟机执行。
2、 声明值和变量
当你键入“8 + 2”,系统会自动分配变量和识别类型:
注意:
val定义的值实际上是一个常量----无法改变值
如果要声明其值可变的变量,可以用var(除非真需要,鼓励用val)
不给出值或者变量的类型时,这个信息可以从初始化它的表达式中推断出来(声明值或者变量,不做初始化会失败)
手动指定类型:val greeting: String = null
变量和函数的类型总是写在变量或者函数名称的后面。
变量声明或者赋值语句之后,不需要使用分号(除非一行多条语句)
3、 常用类型
scala有七种数值类型:Byte、Char、Short、Int、Long、Float和Double,以及一个Boolean类型。与java不同的是,这些类型是类。Scala并不刻意区分基本类型和引用类型。可以对数字执行方法。
在scala中,不需要包装类型。在基本类型和包装类型之间的转换是Scala编译器的工作。
java.lang.String对象“Hello”被隐式地转换成了一个StringOps对象,接着StringOps类的intersect方法被应用。
Int值1首先被转换成RichInt,然后再应用to方法。
在Scala中,我们用方法,而不是强制类型转换来做数值类型之间的转换。
4、 算术和操作符重载
唯一需要注意:a + b => +方法调用 a.+(b)
和Java或C++相比Scala有一个显著的不同,Scala并没有提供++和—操作符,需要使用+= 1 或者-= 1。
为什么Scala因为什么深层次原因而拒绝提供++操作符的(注意,无法实现一个名为++的方法,因为Int类是不可变的,这样一个方法并不能改变某个整数类型的值)。
5、 关于方法调用
如果方法没有参数,并不需要使用括号。例如,StringOps类的API给出了一个sorted方法,没有(),调用该方法将交出字母按顺序排列的新字符串。
重要规则:如果一个无参方法并不修改对象,调用时就不用写括号。
包也可以有包对象,在scala中,_字符是“通配符”,类似于java中的*
通常,类都有一个伴生对象,其方法就跟java中的静态方法一样。
6、 apply方法
def apply(n: Int): Char
s(4)是如下语句的简写:s.apply(4)
注意:偶尔()表示法会跟另一个Scala特性—隐式参数相冲突,例如:
引发一个错误,sorted方法可以用一个隐式的排序参数来调用,但3不是一个有效的排序。可以使用apply:
7、 Scaladoc
在线浏览scaladoc:https://www.scala-lang.org/api/current/
注意每个类名旁边的C和O,它们分别链接到对应的类(C)或伴生对象(O)。对于特质(类似于java的接口),将会看到t和O的标记。
小窍门:
如果想使用数值类型,看看RichInt、RichDouble等。同理,想使用字符串,看看StringOps。
那些数学函数位于scala.math包中,而不是位于某个类中。
有时你会看到名称比较奇怪的函数,比如BigInt有一个方法叫做unary_-,这就是定义前置的负操作符-x的方式。
方法可以以函数作为参数,例如,StringOps的count方法需要传入一个接受单个char并返回true或者false的函数,用于指定哪个字符应当被清点;
s.count(_.isUpper)的作用是清点所有大写字母的数量。
经常会遇到Range或Seq[Char]这样的类,一个是数字区间,一个是字符序列。
在scala中,方括号来表示类型参数。Sqe[Char]是元素类型为char的序列。
有许多互相之间有细微差异的类型表示序列,比如GenSeq、GenIterable、GenTraversableOnce等。它们之间的差别通常都不重要。当你看到这样的结构时,只要把它当作“序列”就好。例如,StringOps类定义了一个方法:
def containsSlice[B](that: GenSeq[B]): Boolean
该方法测试对应的字符串是否包含给定的序列。可以传入一个Range
“Bierstine”.containsSlice(‘r’.to(‘u’)) #将交出true,因为字符串包含了Range(‘r’,’ s’, ‘t’, ‘u’)