Scala 基础

1、Scala的基本数据类型

在Scala中所有的数据类型都是对象,它支持Java的所有基本数据类型:Byte、Char、Short、Int、Long、Float、Double、Boolean,在声明这个数据类型时都要首字母大写,否则会报一个编译时的异常。这些数据类型都位于Scala的“scala”包中,Scala的编译器默认隐式导入的,并且还隐式导入了java.lang包。可以通过“:imports”命令行查看导入了哪些包。

2、定义变量

在Scala中可以通过两种方式定义变量:val 和 var。通过val定义的变量,一旦初始化后就不能够再改变或赋予其它的值(很像java中的final变量)。通过var定义的变量,在初始化之后其值是可以改变的。

a、指定类型

通常情况下,在定义变量时,无需指定变量的数据类型,Scala的解析器会根据变量的值来判断变量的类型。有时候如果必须要指定类型时,可以在变量名称的后面加一个冒号““:”,后跟数据类型的名称。

b、默认值

有时候,在定义变量时并不确定变量的值,可以通过一个”_“占位符来赋一个默认值。如:var str: String = _。需要注意的是,这种情况只适合var 声明的变量,因为val声明的变量在初始化值后,就不能再改变了。

c、延迟初始化

有时,一个变量的值基于一个比较耗时的操作,而在声明变量的时候又不想这样做,因为在声明变量时,Scala默认会计算改变量的值。我们可以通过延迟初始化的方式来改变这种行为,这样只有在第一次使用该变量的时候,才计算改变量的值。如下面的例子:

scala> var a = 1
a: Int = 1
scala> lazy val b = a + 1
b: Int = <lazy>
scala> a = 5
a: Int = 5
scala> b
res1: Int = 6
b的值在最后一行才得到了计算,因为b的值在声明时并没有计算,他使用了a的最新值。

需要提醒的是,延迟初始化只适用于val声明的变量,不适用于var声明的变量。


3、定义函数


如上图,在Scala中使用def 关键字定义函数,后跟函数名、参数、返回值类型、= 、及函数体。其中函数的返回值类型是可选的,因为Scala根据最后一个表达式执行的结果,可以自动推断出函数的返回值类型。另外”=“是也是可以省略,如果返回值类型和”=“号都省略掉,函数将返回”Unit“,Unit就像java中的void,意味着没有返回任何值。如下:

scala> def myFirstMethod(){ "exciting times ahead" }
myFirstMethod: ()Unit

虽然函数的返回值类型可以省略,但是参数的数据类型是必须指定的,因为Scala的类型推断是发生在调用函数时而不是发生在函数声明时。


如果定义的函数很简单,还可以将花括号去掉,如下:

scala> def myFirstMethod() = "exciting times ahead"
myFirstMethod: ()java.lang.String


调用上面定义的函数,将会得到同样的结果。Scala总是尽可能的从代码去掉无用的语法。如果定义的函数没有传递任何参数,还可以把 () 给去掉,这样看起来,就像是在声明变量, 只是val或val关键字用def关键字替换了。如下:

scala> def myFirstMethod = "exciting times ahead"
myFirstMethod: java.lang.String

a、类型参数化
有时,定义一个函数,不确定输入参数的类型,而返回值的类型又和输入参数的类型相关,这种情况,类似于java的泛型。如下例子:

scala> def toList[A](value:A) = List(value)
toList: [A](value: A)List[A]
scala> toList(1)
res16: List[Int] = List(1)
scala> toList("Scala rocks")
res15: List[java.lang.String] = List(Scala rocks)
在定义toList函数时,指定了参数化类型A,当调用toList函数时,将会根据输入参数的数据类型替换A,并返回一个参数化类型的List。

b、函数字面量

对于“函数字面量”的理解,可以参考http://blog.csdn.net/qiruiduni/article/details/46564035

在scala中,可以将一个函数作为参数传递到另一个函数中。


4、流程控制

a、if ... else ..

在Scala中,if和else块和其它语言很相似,区别的地方是Scala的if/else是一个表达式,并且有返回值,返回值是最后表达式语句执行的结果。

Scala不支持“?”操作符。

b、while和do-while

while和do-while块和其它语言的基本相同。

c、for

Scala中的for循环和java中的很相似,只是表现形式不同,如下:

java中的for循环

<pre name="code" class="html">for(File file: files) {
      String filename = file.getName();
      if(filename.endsWith(".scala")) System.out.println(file);
} 
 Scala中的for循环 

<pre name="code" class="html">val files = new java.io.File(".").listFiles
for(file <- files) { 
    val filename = file.getName
    if(fileName.endsWith(".scala")) println(file) 
}
 

</pre><p>区别在于“file <- files” 表达式,在Scala中称作generator(生成器),在“<-”符号的右边为集合,左边为集合中的每一个元素。</p><p>对于上句,还可以做进一步的简写:</p><p><pre name="code" class="html">for(
    file <- files; 
    fileName = file.getName; 
    if(fileName.endsWith(".scala"))
) println(file)
Scala允许在for表达式中定义变量和做逻辑判断,需要注意的是,在for表达式中定义的变量都是val类型,不能被修改。

下图为for循环表达式的语句结构:


例子:

scala> val aList = List(1, 2, 3)
aList: List[Int] = List(1, 2, 3)
scala> val bList = List(4, 5, 6)
bList: List[Int] = List(4, 5, 6)
scala> for { a <- aList; b <- bList } println(a + b)
5
6
7
6
7
8
7
8
9

如上例,如果在for表达式中有多个generators(生成器)时,从左至右,每个遍历每个generator。如本例,首先遍历aList集合,当a=1时,会和bList集合中的每一个元素相加,然后遍历aList集合中的下一个元素,重复以上的步骤。当有多个generator时,通常用“{}”大括号括起来,也可以用“()”圆括号,用哪种根据自己爱好。


在Scala中的for循环有两种表现形式:imperative form(命令形式)和 functional  form (函数形式),像上面列举的例子都是imperative form,这种形式指定要循环执行的表达式语句,并不会返回任何东西,而functional  form将会返回值,看下面的例子:

scala> val result = for { a <- aList; b <- bList } yield a + b    
result: List[Int] = List(5, 6, 7, 6, 7, 8, 7, 8, 9)
scala> for(r <- result) println(r)
5
6
7
6
7
8
7
8
9
scala> val xmlNode = <result>{result.mkString(",")}</result>
xmlNode: scala.xml.Elem = <result>5,6,7,6,7,8,7,8,9</result>
这个for表达式语句通过“yield”关键字返回一个相加后的List集合。 functional  form这种形式的循环和imperative form形式的循环相比,提高了重用性。

在Scala中,任何事物都是一个表达式,并且有返回值。

5、Pattern matching(模式匹配)

Scala中的模式匹配和java中switch语句相似,不同的是在Scala中不必再为每个case指定一个break,因为Scala不允许在进入其它的case块中,并且用“case _”替代了java的default项,代表匹配其它的一切,“case _” 为可选项,当去掉后,如有没有找不到匹配项,会抛出一个MatchError异常。

在java中,switch只能匹配基本数据类型和枚举类型,但是在Scala中可以匹配String和复杂的值,类型,变量、常量、构造函数等。如下例子:

def printType(obj: AnyRef) = obj match {
  case s: String => println("This is string")
  case l: List[_] => println("This is List")
  case a: Array[_] => println("This is an array")
  case d: java.util.Date => println("This is a date")
}
scala> printType("Hello")
This is string
scala> printType(List(1, 2, 3))
This is List
scala> printType(new Array[String](2)) 
This is an array
scala> printType(new java.util.Date())
This is a date
这个例子演示了变量和类型的匹配。

有时需要在case子句中做些逻辑判断,可以像下面的例子书写:

def rangeMatcher(num:Int) = num match {
  case within10 if within10 <= 10 => println("with in 0 to 10")
  case within100 if within100 <= 100 => println("with in 11 to 100")
  case beyond100 if beyond100 < Integer.MAX_VALUE => println("beyond 100"
}
6、异常处理
Scala的异常处理和java有点不同,它允许可以定义单一的try/catch块,和在一个单一的catch块中使用pattern matching来捕获异常。例子:

def rangeMatcher(num:Int) = num match {
  case within10 if within10 <= 10 => println("with in 0 to 10")
  case within100 if within100 <= 100 => println("with in 11 to 100")
  case _ => throw new IllegalArgumentException(
            "Only values between 0 and 100 are allowed")
}
scala> try { 
          rangeMatcher1(1000)
      } catch { case e: IllegalArgumentException => e.getMessage }
res19: Any = Only values between 0 and 100 are allowed

在Scala中没有检查异常(checked Exception)的概念,所有的异常都是非检查的异常,因为对一个程序员来说,可以自由决定想要捕获的异常。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值