Scala :类型、控制结构和函数
标识符:
-
首字符为字母,后续字符任意字母和数字,美元符号,可后接下划线_
-
首字符为操作符,后续字符为任意操作符
-
用反引号`....`包括的任意字符串,即使是关键字也可以
-
Scala中有些保留字,不能用作标识符,但是反引号括起除外,如yield在Scala中就是保留字
声明值和变量:
val:是只读变量,不能被重新赋值
var:是可变变量,可以被重新赋值
Scala中,可以进行类型的自动推断,所以定义变量时不需要显式的指定变量的类型。
显式得指定:var n:int = 10
常用类型:
Any
AnyVal是所有值类型的父类型 AnyRef是所有引用类型的父类型
AnyVal的左分支是数值类型 所有的Java的数据结构(如集合、数组)
Unit是空类型,唯一一个实例化对象是:() scala可以直接使用Java的类
StringOps是String类的扩展 Null只有一个实例化对象null,是所有引用类型的子类型
Nothing没有实例化对象,是所有类型的子类型
在java中不允许运算符重载,在scala中可以。在scala中一切皆对象。运算符本质上也是一个方法。
在scala中调用方法,可以使用空格。dog1.play() <—>dog1 play()
Scala中没有++、--操作符,需要通过+=、-=来实现同样的效果
Scala中的包不仅仅用来管理类,还可以作为对象使用,所以导包的时候等同于把包对象导入到当前的环境中,所以包对象中声明的函数可以直接调用:
scala> import scala.math._
scala> sqrt(100)
在Scala中没有静态这个概念。所有Object关键字定义的内容均为静态。
例:
class Array{ object Array{
} }
前者中的静态内容都要抽到后者中去,后者成为前者的伴生类对象,前者称为后者的伴生类。
Array伴生类对象中的两个方法:
Array arr = “hello"
apply方法:用于构造或获取元素。 arr(4) =“hello”(4)= Array.apply(4) 即o
update方法:用于更新数组内的元素。 arr(4) = 5 <==> arr.update(4,5) 把第四个元素改成5
option类型
在scala中,使用get()获取集合中的值,是返回option类型的,该类型是个集合类型。
option中包含some集合和none集合
Some集合:当获取到元素的时候,该元素会被返回到some集合中。若想得到其中的值,则Some().get。
None集合:当获取不到元素的时候,会返回None
Symbol类型
1.属于基本类型,被映射成scala.Symbol
2.当两个Symbol值相等时,指向同一个实例
3.Symbol类型存在的意义:作为不可变的字符串,同时不必重复地为相同对象创建实例,节省资源。这类似ruby的设计。
4.定义变量val s=‘my_symbol时,s值即为
s:Symbol = ’my_symbol。
而s.name为Sting类型,值为"my_symbol"
if/eles
if/else可以有返回值。返回值为满足条件的最后一行的代码
因此 scala中没有三目运算符
while循环
和java没有多大区别。返回值是Unit的对象()
while中没有break。
while的打断(用以下方式或者flag方式):
import scala.util.control.Breaks._
breakable{
while(n<=20){
n+1
if(n==18){
break()
}
}
}
所谓的break方法其实就是抛出异常,让breakable方法返回
多重while循环的打断:定义两个Breaks
for循环
可以使用“守卫”。to 前闭后闭。 until前闭后开。to和until只能正序,相当于一个步长为1的range,若要倒叙,直接使用range。
for(i <- 1 to 3; j <- 1 to 3){
print(i * j + " ")
}
则结果为:1 2 3 2 4 6 3 6 9(i=1,j=1; i=1,j=2; i=1,j=3; i=2,j=1……)
for(i <- 1 until 3; j <- 1 until 3) {
print(i * j + " ")
}
则结果为:1 2 2 4 (i=1,j=1 ; i=1,j=2 ; i=2,j=1 ; i=2,j=2)
守卫:也称之为:保护式,可以实现类似Continue的功能
for(i <- 1 to 3 if i != 2) {
print(i + " ")
}
则结果为:1 3
引入变量:
for(i <- 1 to 3; j = 4 - i) {
print(j + " ")
}
则结果为:3 2 1
保存遍历中的结果:yield
val for5 = for(i <- 1 to 10) yield i
println(for5)
则结果为Vector(1,2,3,4,5,6,7,8,9,10)
直接使用{}:花括号中一行一句代码
for{
i <- 1 to 3
j = 4 - i}
print(i * j + " “)
}
函数的定义:
完整定义方式:def 函数名(参数名1:参数类型1,参数名2,参数类型2):返回类型={函数体}
def play(a1:Int,a2:String):String = {
“hello"
}
Scala中的函数可以根据函数体最后一行代码自行推断函数返回值类型。那么在这种情况下,return关键字可以省略,既然Scala可以自行推断,所以在省略return关键字的场合,返回值类型也可以省略。
如果函数明确使用return关键字,那么函数无法省略返回值类型。(如果声明返回值类型为Unit,则使用return关键字也不会有返回值)
若需要传参数则一定要指定类型
def play1(a1:Int,a2:String)= {
“hello"
}
//可选参数,调用时可传可不传,不传则为默认值
def shout4(content: String, leg: Int = 4) = {
println(content + "," + leg)
}
//带名参数
def f6 ( p1 : String = "v1", p2 : String ) {
println(p1 + p2);
}
调用:f6(p2="v2")
//变长参数,所有参数会被转换成一个Seq序列
def sum(args: Int*) = {
}
//递归函数,一定要指定返回值类型
//定义函数的时候,如果没有参数,则可以省略参数体的小括号,但是,在函数调用时也不能加。
def play2={
}
//不省略的话,调用的时候可加可不加。
def play2()={
}
过程:将函数的返回类型为Unit的函数称之为过程。如果明确函数没有返回值,那么等号可以省略
定义过程(返回值为空)的形式:
def fun1() : Unit = {
}
//不省略等号,会自动推断返回值类型
def fun2()={
}
//省略等号,返回值永远是空。(推荐这样定义过程)
def fun3() {
}
懒值:定义的时候不会执行,用的时候才执行。可以实现类似提前定义的效果
object Lazy {
def init(): String = {
println("init方法执行")
"嘿嘿嘿,我来了~"
}
def main(args: Array[String]): Unit = {
lazy val msg = init()
println("lazy方法没有执行")
println(msg)
}
}
则结果为:
lazy方法没有执行
init方法执行
嘿嘿嘿,我来了~
异常:
Scala中的异常都不用显式捕获。
捕获异常实际上是模式匹配
Error
Throwable
Exception
object ExceptionSyllabus {
def divider(x: Int, y: Int): Float= {
if(y == 0) throw new Exception("0作为了除数")
else x / y
}
def main(args: Array[String]): Unit = {
try {
println(divider(10, 3))
} catch {
case ex: Exception => println("捕获了异常:" + ex)
} finally {}
}
}