0x00开始安装
1. JVM
Scala是运行在JVM平台上的,所以你需要有JDK环境
2.安装Scala
Windows安装Scala编译器
-
访问Scala官网http://www.scala-lang.org/下载Scala编译器安装包,目前最新版本是2.12.x
下载scala-2.11.8.msi后点击下一步就可以了(一般会自动配置上环境变量)。也可以下载scala-2.11.8.zip解压即可
检查环境变量是否成功,打开CMD(也可以去path里看有没有$SCALA_HONE$)输入scala
Linux安装Scala编译器
下载Scala地址https://www.scala-lang.org/download/2.11.8.html
然后解压Scala到指定目录
tar -zxvf scala-2.11.8.tgz -C /opt/soft
配置环境变量,将scala加入到PATH中
- vim /etc/profile
export JAVA_HOME=/opt/soft/jdk1.8
export PATH=$PATH:$JAVA_HOME/bin:/opt/soft/scala-2.11.8/bin
Idea安装
目前Scala的开发工具主要有两种:Eclipse和IDEA,这两个开发工具都有相应的Scala插件,如果使用Eclipse,直接到Scala官网下载即可http://scala-ide.org/download/sdk.html。
由于IDEA的Scala插件更优秀,大多数Scala程序员都选择IDEA,可以到http://www.jetbrains.com/idea/download/下载,点击下一步安装即可,安装时如果有网络可以选择在线安装Scala插件。
离线安装Scala插件:
1.安装IDEA,点击下一步即可。
2.下载IEDA的scala插件
插件地址: https://plugins.jetbrains.com/plugin/1347-scala
3.安装Scala插件:Configure -> Plugins -> Install plugin from disk -> 选择Scala插件 -> OK -> 重启IDEA
在线安装Scala插件:
idea打开: Settings -> Plugins -> 搜索Scala -> lnstall ->重启idea
记得设置补全变量类型:
0x01基本语法
- Scala代码
1 | object HelloScala { |
- 对比Java代码
1 | public class HelloJava { |
0x01变量、类型、操作符
1.变量声明
Scala声明变量有两种方式,一个用val,一个用var。
val/var 变量名 : 变量类型 = 变量值。
val和var声明变量时都必须初始化。
val定义的值是不可变的,它不是一个常量,是不可变量,或称之为只读变量。相当于java里用final修饰的变量
val定义的变量虽然不能改变其引用的内存地址,但是可以改变其引用的对象的内部的其他属性值。
为了减少可变性引起的bug,应该尽可能地使用不可变变量。
变量类型可以省略,解析器会根据值进行推断。
关键字 | 是否可以更改 |
---|---|
var 声明变量 | 可以 |
val 声明常量 | 不可以 |
Scala 语言鼓励程序员使用 val 来声明,因为Scala语言设计哲学中,认为流程中修改变量值,会造成程序逻辑复杂,不易维护,不易并行计算
1 | object VariableDemo { |
2.常用数据类型
Scala和Java一样,有多种数值类型Byte、Char、Short、Int、Long、Float、Double类型和1个Boolean类型。
Boolean | true 或者 false |
---|---|
Byte | 8位, 有符号 |
Short | 16位, 有符号 |
Int | 32位, 有符号 |
Long | 64位, 有符号 |
Char | 16位, 无符号 |
Float | 32位, 单精度浮点数 |
Double | 64位, 双精度浮点数 |
String | 其实就是由Char数组组成 |
- Scala继承层级
统一类型,是Scala的又一大特点。
- Any
在scala中,所有的类,包括值类型,都最终继承自一个统一的根类型Any,Any类是跟节点
Any中定义了isInstanceOf、asInstanceOf方法,以及哈希方法等。AnyVal和AnyRef都扩展自Any类。
- AnyVal
所有的值都是类类型都是AnyVal的子类,
- AnyRef
所有其他类都是AnyRef的子类,类似Java的Object。
更特别的是,Scala中还定义了几个底层类(Bottom Class),比如Null和Nothing。
- Null
是所有引用类型的子类型,Null类只有一个实例对象,null,类似于Java中的null引用。null可以赋值给任意引用类型,但是不能赋值给值类型。
- Nothing
是所有类型的子类型。Nothing类型没有实例。它对于泛型结构是有用处的,举例:
空列表Nil的类型是List[Nothing],它是List[T]的子类型,T可以是任何类。
Nothing可以作为没有正常返回值的方法的返回类型,非常直观的告诉你这个方法不会正常返回,而且由于Nothing是其他任意类型的子类,他还能跟要求返回值的方法兼容。
- Unit
用来标识过程,也就是没有明确返回值的函数。由此可见,Unit类似于Java里的void。Unit只有一个
对象实例,(),这个实例也没有实质的意义。
- Any
在scala中,Any类是所有类的超类,Any有两个子类:AnyVal和AnyRef
- AnyVal- 所有值类型的基类, 它描述的是值,而不是代表一个对象。
它包括 9个AnyVal 子类型:
- scala.Double
- scala.Float
- scala.Long
- scala.Int
- scala.Char
- scala.Short
- scala.Byte
上面是数字类型。
还包括scala.Unit 和 scala.Boolean 是非数字类型。
- AnyRef- 是所有引用类型的基类。除了值类型,所有类型都继承自AnyRef 。
- 注意:
与Java中的数据类型不同,Scala并不刻意区分基本类型和引用类型,所以这些类型都是对象,可以调用相对应的方法。
String直接使用的是java.lang.String. 不过,由于String实际是一系列Char的不可变的集合,Scala中大部分针对集合的操作,都可以用于String.
具体来说,String的这些方法存在于类scala.collection.immutable.StringOps中。
由于String在需要时能隐式转换为StringOps,因此不需要任何额外的转换,String就可以使用这些方法。
每一种数据类型都有对应的Rich* 类型,如RichInt、RichChar等,为基本类型提供了更多的有用操作。
3.操作符重载
Scala中的+ - * / %等操作符的作用与Java一样,位操作符 & | ^ >> <<也一样。但是有一点区别,这些操作符实际上是方法。
那么既然+ - * / %是方法,那么就可以进行操作符重载,完成特殊的运算
你几乎可以用任何符号来为方法命名。
注意:Scala中没有++、–操作符,需要通过+=、-=来实现同样的效果。
- 举例
1 | package com.bigdata.basic |
- 运算符重载 伪代码
- 操作符总结
1) 如果想在变量名、类名等定义中使用语法关键字(保留字),可以配合反引号反引号:
1 | val `val` = 123 |
2) 中置操作符,A操作符B等同于A.操作符(B) ==> a + b ==> a.+(b)
3) 后置操作符,A操作符等同于A.操作符,如果操作符定义的时候不带()则调用时不能加括号
4) 前置操作符,+、-、!、~等操作符A等同于A.unary_操作符。
5) 赋值操作符,A操作符=B等同于A=A操作符B
0x02判断和循环
1.条件表达式
Scala的的条件表达式比较简洁,且Scala中if else表达式是有返回值的,如果if或者else返回的类型不一样,就返回Any类型(所有类型的公共超类型)。
如果缺少一个判断,什么都没有返回,但是Scala认为任何表达式都会有值,对于没有返回值的,使用Unit类,写做(),叫做无用占位符,相当于java中的void
1 | package com.bigdata.basic |
2.块表达式
定义变量时用{} 包含一系列表达式,其中块的最后一个表达式的值就是块的值。
1 | package com.bigdata.basic |
1 | package com.bigdata.basic |
3.循环
在scala中有for循环和while循环,用for循环比较多
- while
1 | package com.bigdata.basic |
注意:
与If语句不同,While语句本身没有值,即整个While语句的结果是Unit类型的()
scala并没有提供break和continue语句来退出循环,如果需要break,可以通过几种方法来做
1、使用Boolean型的控制变量
2、使用嵌套函数,从函数中return
3、使用Breaks对象的break方法。
- for
for循环语法结构:
for (变量 <- 表达式/数组/集合)
1 | package com.bigdata.basic |
0x03 方法和函数
1.调用方法和函数
在scala中,函数与方法是不同的东西。后面我们再详细探讨。首先我们要学会使用scala来调用函数与方法。
1 | object MethodAndFunctionDemo { |
2.定义方法
def 方法名(参数名1: 参数类型1, 参数名2: 参数类型2) : 返回类型 = {方法体}
1 | object MethodAndFunctionDemo2 { |
3.定义函数
val函数名称 :(参数类型)=>函数返回值类型 = (参数名称:参数类型)=>函数体
或者简写
val函数名名称 = (参数名称:参数类型) => 函数体
带有一个参数的函数的类型是function1,带有两个是function2,以此类推
1 | object FunctionDemo { |
4.方法和函数的区别
方法:和之前理解的方法一样,是封装了完成某些功能的代码块,所属于某一个类或对象
函数:在Scala中,函数一个对象,那么既然是对象的话,函数就可以当作参数被传递,还可以使用函数打点调用方法
在函数式编程语言中,函数是“头等公民”,函数是一个对象,继承自FuctionN。它可以像任何其他数据类型一样被传递和操作
1 | def main(args: Array[String]): Unit = { |
函数对象有apply
、curried
、toString
、tupled
这些方法。而方法不具有这些特性。
- 案例:首先定义一个方法,再定义一个函数,然后将函数传递到方法里面
1 | object MethodAndFunctionDemo3 { |
5.将方法转换成函数(神奇的下划线)
将方法转换成函数,只需要在方法的后面加上一个下划线
1 | def main(args: Array[String]): Unit = { |
6.总结
1 | object FunctionDemo { |
0x04其他
1.懒值
当val被声明为lazy时,初始化将被推迟,直到我们首次对此取值,适用于初始化开销较大的场景。
1 | object LazyDemo { |
2.异常处理
Scala的异常的工作机制和Java一样,但是Scala没有“checked”受检异常,你不需要声明函数或者方法可能会抛出某种异常。
(受检异常在编译器被检查,java必须声明方法所会抛出的异常类型)
抛出异常:用throw关键字,抛出一个异常对象。所有异常都是Throwable的子类型。throw表达式是有类型的,就是Nothing,因为Nothing是所有类型的子类型,所以throw表达式可以用在需要类型的地方。
捕捉异常:在catch的代码里,使用一系列case子句(借用了模式匹配的思想来做异常的匹配)
异常捕捉的机制与其他语言中一样,如果有异常发生,catch字句是按次序捕捉的。因此,在catch字句中,越具体的异常越要靠前,越普遍的异常越靠后。
如果抛出的异常不在catch字句中,该异常则无法处理,会被升级到调用者处。
finally字句用于执行不管是正常处理还是有异常发生时都需要执行的步骤,一般用于对象的清理工作。
1 | object ExceptionDemo { |