01 Scala基础
1.1 Scala解释器
启动解释器的步骤如下:
- 安装scala
- 确保Scala/bin目录位于系统path中
- 在你的操作系统中打开命令行窗口
- 输入scala并按enter
现在你已经可以开始用Scala啦
scala> 1+1
res0: Int = 2
scala> 3+res0
res1: Int = 5
scala> "Hello,"+res1
res2: String = Hello,5
scala>
正如你所看到的那样,Scala解释器读到一个表达式,对它进行求值,将它打印出来,再接着读下一个表达式。
这个过程被称为“读取——求值——打印”循环(read-eval-print loop), 即REPL。
实际上,Scala并不是一个解释器。你输入的内容被快熟的编译成字节码,然后这段字节码交由Java虚拟机执行。正因为如此,大家更喜欢将Scala称为REPL。
你可以再REPL中键入:help
看到一组有用的清单。值得一提的是,所有的命令都可以用缩写,比如用:he
代表help
。
1.2 声明值和变量
除了使用res0、res1这些名称之外,你可以自定义变量名称。
scala> val answer=1+1
answer: Int = 2
scala> 3+answer
res5: Int = 5
//以val定义的其实是一个常量
//你无法改变他的值
scala> answer=0
<console>:8: error: reassignment to val
answer=0
^
//如果要声明其值可变的变量——————>使用var声明
scala> var count=0
count: Int = 0
scala> count = 1
count: Int = 1
scala>
- 以
val
定义的变量其实是一个常量——你无法改变它的值,如果想定义一个其值可变的变量,可以用var
来定义。 - 在Scala中,提倡用
val
,除非你一定需要改变它的内容。 - 声明值时需要初始化,不然会报错
- 声明变量不必要指定变量类型,你也可以指定,但是注意
在Scala中,变量或函数的类型,总是写在变量或者函数名称的后面。比如val name: String,这与Java是反过来的。
scala> val name: String = "Chris"
name: String = Chris
scala>
你可能注意到在,变量声明或赋值语句之后,我们没有添加分号 “ ;”。
在Scala中,仅当同一行代码中存在多条语句时才需要用分号隔开。
- 可以将多个变量一起声明
scala> val a,b =100
a: Int = 100
b: Int = 100
scala> val c,d : String="null"
c: String = null
d: String = null
scala>
1.3 常用类型
和Java一样,Scala也有7种数值类型:
- Byte
- Char
- Short
- Int
- Long
- Float
- Double
- Boolean
与Java不用的时这些类型是类。Scala并不刻意区分基本类型和引用类型。你可以对数字执行方法,例如:
scala> val c,d : String="null"
c: String = null
d: String = null
scala> 1.toString()
res7: String = 1
scala> 1.to(10)
res8: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala>
intersect
方法将交出两个字符串共通的一组字符串
scala> "Hello".intersect("World")
res10: String = lo
在Scala中我们使用方法而不是强制类型转换,来做数值类型之间的转换。
scala> 99.9.toInt
res11: Int = 99
scala> 99.toChar
res12: Char = c
scala> 99.toString
res13: String = 99
1.4 算术和操作符重载
Scala的算术操作符和你在Java或C++中的效果是一样的,+ - * / %等操作符完成的是它们通常的工作。
不同的是,在Scala中,这些操作实际上是方法。
例如a+b
是如下方法的简写
a.+(b)
这里的+是方法名
Scala不会对方法名中,使用的是非字母或数字带有偏见。
通常来说,你可以用
a 方法 b
作为以下代码的简写:
a.方法(b)
例如
1 to 10
其实是
1.to(10)
Scala没有
--
和++
运算符,需要使用+=1
或者-=1
因为Int类是无法改变的,Scala的设计者认为不值得为少敲一个键而增加一个特例。
1.5 关于方法调用
前面提到的intersect
就是一种方法的调用。
如果方法没有参数,不需要使用括号。例如sorted
方法,
scala> "liusong".sorted
res15: String = gilnosu
最重要的规则是,乳沟一个无参方法并不修改对象,调用时就不用括号。
你可以引入一个包,然后不带任何前缀使用包对象里的方法:
scala> import scala.math._
//这里的 _ 相当于Java里的 * ,也是通配符
import scala.math._
scala> sqrt(2)
res17: Double = 1.4142135623730951
scala> pow(2,3)
res18: Double = 8.0
scala> min(3,Pi)
res20: Double = 3.0
如果你不引入scala.math包,就添加包名来使用:
scala> scala.math.sqrt(2)
res21: Double = 1.4142135623730951
通常,类都有一个伴生对象(companion object),其方法就跟Java中的 静态方法 一样。
举个栗子,scala.math.BigInt类的BigInt伴生对象,有一个生成指定位数的随机质数的方法probablePrime
:
scala> BigInt.probablePrime(100, scala.util.Random)
res22: scala.math.BigInt = 1196261416829979960992808836207
这里的Random
是一个单例随机数生成器对象。
1.6 apply方法
在Scala中,我们通常都会使用类似于函数调用的语法。比如:
scala> val s ="Hello"
s: String = Hello
scala> s(4)
res0: Char = o
你可以把这种用法当作()操作符的重载形式,这背后其实是一个名为apply的方法。
scala> s.apply(4)
res1: Char = o
有时()表示法会和Scala的另一个特性——隐式参数——相冲突:
scala> "liusong".sorted(3)
<console>:8: error: type mismatch;
found : Int(3)
required: scala.math.Ordering[?]
"liusong".sorted(3)
^
可以显示地调用apply
:
scala> "liusong".sorted.apply(3)
res5: Char = n
1.7 Scaladoc
Java程序员使用Javadoc来浏览Java API。Scala也有自己的版本,叫作Scaladoc。 传送门
后记
- 在Scala REPL中键入3. , 然后按Tab键。有哪些方法可以被应用?
- 如何获取字符串的首字母和尾字母?
- 字符串方法小结:
方法名 | 含义 | 用法 |
---|---|---|
substring | 字符串切片 | “liusong”.substring(3,6) //交出son |
split | 将字符串分割成数组形式 | “abccabccabcc".split(“cc”,4) //交出 Array(ab, ab, ab, “”) |
toUpperCase | 将字符串转换成大写 | “liusong”.toUpperCase //交出 LIUSONG |
endsWith | 判断字符串结尾字符是否为xxx | “liusong".endsWith(“song”) //交出true |
replace | 替换特定字符 | “liuusoug”.replace(“uu”,“a”) //交出liasoug |
length | 计算字符串长度 | ”hello".length //交出5 |
contains | 判断字符串是否包含特定字符 | “liusong".contains(‘s’) //交出true |
更多字符串方法 | 见接口文档-StringOps