在拥有java基础上学习scala,注意以下几点
var | val 变量名 [: 变量类型] = 变量值
val name: String = "nico"
val name= "nico"
val name :String = 123 (报错123为int)
val name :String = "nico" name = "mc" (报错reassignment to val)
Unit类型用来标识过程,类似java里的void,只有一个实例()
null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)
Nothing可以作为没有正常返回值的方法的返回类型,是其他任意类型的子类
//前后闭合
for (i <- -1 to 3) {
printf("数字i为%d\n", i)
}
//前闭后开
for (j <- -1 until 3) {
printf("数字j为%d\n", j)
}
//循环守卫 条件true则进入循环 false跳出循环 相当于if写在for里
for (k <- -1 to 3 if k != 2) {
printf("数字k为%d\n", k)
}
//循环引入变量 没有关键字val/var 如果是()要用分号隔开 如果用{}换行则不用写分号
//for{i <- 1 to 4
// j = 4 - i
// k = i + 1}{......}
for (i <- 1 to 4; j = 4 - i; k = i + 1) {
println(s"i=${i} j=${j} k=${k}" )
}
//嵌套for循环
for(i <- 1 to 2; j <- 1 to 2) {
println(" i =" + i + " j = " + j)
}
//将便利结果返回到一个新的集合Vector中,使用yield关键字,yield 可以写代码块
val res = for (i <- 1 to 10) yield (i * 2)
println("res=" + res)
val res2 = for (i <- 1 to 10) yield {
if (i % 2 == 1) {
i
}else {
()
}
}
println("res2=" + res2)
//控制步长
for (i <- Range(1,10,3)) { //until
println("i=" + i)
}
输出结果:
数字i为-1
数字i为0
数字i为1
数字i为2
数字i为3
-----------
数字j为-1
数字j为0
数字j为1
数字j为2
-----------
数字k为-1
数字k为0
数字k为1
数字k为3
-----------
i=1 j=3 k=2
i=2 j=2 k=3
i=3 j=1 k=4
i=4 j=0 k=5
-----------
i =1 j = 1
i =1 j = 2
i =2 j = 1
i =2 j = 2
-----------
res=Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
res2=Vector(1, (), 3, (), 5, (), 7, (), 9, ())
-----------
i=1
i=4
i=7
Scala内置控制结构特地去掉了break和continue,推荐使用函数式的风格解决break和contine的功能,而不是一个关键字
break:
breakable { //不加breakable 会被下面的break()报错崩溃
var n = 1
while (true) {
println("n=" + n)
n += 1
if (n == 3) {
//def break(): Nothing = { throw breakException } 抛出breakException
break()
}
}
}
输出结果
n=1
n=2
continue:
可利用上方守卫循环实现continue
for (k <- -1 to 3 if k != 2) {
printf("数字k为%d\n", k)
}
函数定义:
def 函数名 ([参数名: 参数类型], ...)[[: 返回值类型] =] { 语句... //完成某个功能 return 返回值 }
其中:
1) 函数可以有返回值,也可以没有
2) 返回值形式1: //[ : 返回值类型 =] 表示有返回值,并且指定了返回值的类型
3) 返回值形式2: //[ = ], 表示返回值类型,使用类型推导
4) 返回值形式3: //[ ] 空的 ,表示没有返回值,即使有return 也不生效
def sum(n1: Int, n2: Int): Int = {
// Scala中的函数可以根据函数体最后一行代码自行推断函数返回值类型。那么在这种情况下,return关键字可以省略
// return n1 + n2
n1 + n2
}
def sum2(n1: Int, n2: Int) = {
// return n1 + n2 因为Scala可以自行推断,所以在省略return关键字的场合,返回值类型也可以省略
n1 + n2
}
//如果没写返回值类型,不能用return 否则报错
def sum3(n1: Int, n2: Int) = {
//return n1 + n2 报错!!!
n1 + n2
}
//在scala中,支持可变参数, 可变参数只能放在最后
def sum4(n:Int,args:Int*): Int = {
var res = n
for (i<-args) {
res += i
}
res
}
//如果明确函数无返回值或不确定返回值类型,那么返回值类型可以省略(或声明为Any)
def f1(n: Int): Any = {
if (n == 1) {
10
} else {
"yes"
}
}
//将函数的返回类型为Unit的函数称之为过程(procedure),如果明确函数没有返回值,那么等号可以省略
def sayHello(): Unit = {
println("sayHello")
}
def sayHello1() = {//如果函数声明时没有返回值类型,但是有 = 号,可以进行类型推断最后一行代码。这时这个函数实际是有返回值的,该函数并不是过程。
println("sayHello1")
}
def sayHello2() {
println("sayHello2")
}
惰性函数:尽可能延迟表达式求值
// lazy 不能修饰 var 类型的变量
def main(args: Array[String]): Unit = {
lazy val res: Int = sum(1, 2)
println(res)
lazy val data = 10 // 不但是调用函数时,加了 lazy ,会导致函数的执行被推迟,我们在声明一个变量时,如果给声明了 lazy ,那么变量值得分配也会推迟。
}
def sum(i: Int, j: Int): Int = {
i + j
}
}
// 案例一
//
def main(args: Array[String]): Unit = {
try {
lazy val i = 20/0
println(i)
}
catch {
case exception: Exception => println("异常信息" + exception.getMessage)
}
finally {
println("最终处理")
}
// 案例二
//3) 用throw关键字,抛出一个异常对象。所有异常都是Throwable的子类型。throw表达式是有类型的,就是Nothing,因为Nothing是所有类型的子类型,所以throw表达式可以用在需要类型的地方
def main(args: Array[String]): Unit = {
// lazy val res: Int = sum(1, 2)
// println(res)
try {
val res = test()
println(res.toString)
}
catch {
case exception: Exception => println("异常信息:" + exception.getMessage)
}
finally {
println("最终出处理结果")
}
def test(): Nothing = {
throw new Exception("不对")
}
}
输出结果:
异常信息/ by zero
最终处理
异常信息:不对
最终出处理结果