1. 程式人生 > >菜鳥零號 kungfu~peng

菜鳥零號 kungfu~peng

Scala程式設計

Scala是什麼

  • Scala是一門多正規化的程式語言,設計來面向物件和函數語言程式設計的各種特性,Scala執行在java虛擬機器上,併兼容現有的Java程式,Scala原始碼被編譯成位元組碼,並可以呼叫現有的Java類庫。

第一個Scala程式

  • 程式程式碼

    package com.peng.scala
    
    object Test {
      def main(args: Array[String]) {
        print("Hello World!");
      }
    }
    
  • 執行結果
    Hello World!
    

Scala特性

  1. 面向物件
    • Scala是一種純面向物件的語言,每個值都是物件。物件的資料型別以及行為由類和特質進行描述。類抽象機制的擴充套件有兩種途徑:一種是子類繼承,另一種是靈活的混入機制。這兩種途徑能避免多重繼承的種種問題。
  2. 函數語言程式設計
    • Scala也是一種函式式語言,其函式也能當成值來使用,Scala提供了輕量級的語法定義匿名函式,支援高階函式,允許巢狀多層函式,支援柯里化【是把接受多個引數的函式變換成接受一個單一引數(最初函式的第一個引數)的函式,並且返回接受餘下的引數且返回結果的新函式的技術】,Scala的case class及其內建的模式匹配相當於函數語言程式設計語言中常用的代數型別。更進一步來說,可以使用Scala的模式匹配,編寫類似正則表示式的程式碼處理XML資料。
  3. 靜態型別
    • Scala具備型別系統,通過編譯時檢查,保證程式碼的安全性和一致性。型別系統具體支援以下特性
      1. 泛型類
      2. 協變和逆變
      3. 標註
      4. 型別引數的上下限約束
      5. 把類別和抽象型別作為物件成員
      6. 符合型別
      7. 引用自己時顯示指定型別
      8. 檢視
      9. 多臺方法
  4. 擴充套件性
  5. Scala的設計秉承一項事實,即在實戰中,某個領域特定的應用程式開發往往需要特定於該領域的語言擴充套件。Scala提供了許多獨特的語言機制,可以以庫的形式輕易無縫新增新的語言結構。
    • 任何方法可用作字首或字尾操作符
    • 可以根據預期型別自動構造閉包
  6. 併發性
  7. Scala使用Actor作為其併發模型,Actor是類似執行緒的實體,通過郵箱發收訊息,Actor可以複用執行緒,因此可以在程式中使用數百萬個Actor,而執行緒只能建立數千個。在2.10之後的版本中,使用Akka作為其預設的Actor實現。

Scala在Windows上的安裝

  • 安裝步驟
    1. 下載Scala的msi二進位制包
    2. 進行安裝
    3. 環境變數設定
      • SCALA_HOME=安裝Scala的路徑
      • Path中;%SCALA_HOME%\bin;%SCALA_HOME%\jre\bin;
      • ClassPath中;%SCALA_HOME%\bin;%SCALA_HOME%\lib\dt.jar;%SCALA_HOME%\lib\tools.jar.;
    4. 測試Scala環境
      • win+r快捷鍵調出cmd,輸入scala

Scala基礎語法

  • Scala與Java語言的最大區別就是Scala語句末尾的分號是可選的
  • Scala可以認為是物件的集合,通過呼叫彼此的方法來實現訊息傳遞
    • 物件:物件有屬性和行為
    • 類:類是物件的抽象,而物件是類的具體例項
    • 方法:方法描述的基本的行為,一個類可以包含多個方法
    • 欄位:每個物件都有它唯一的例項變數集合,即欄位。物件的屬性通過給欄位賦值來建立。

dos視窗下的Scala程式設計

指令碼形式的Scala程式設計

Scala的基本語法

  • Scala的基本語法需要注意一下幾點
    1. 區分大小寫:Scala對於大小寫是敏感的
    2. 類名:對於所有的類名的第一個字母要大寫
    3. 方法名稱:所有的方法名稱第一個字母要小寫
    4. 程式檔名,程式的檔名應該與物件名稱完全匹配,雖然新的版本沒有這種要求了,但是還是建議儲存這種習慣
    5. 方法開始處理的入口def main(args:Array[String]),這是每一個Scala程式的強制程式入口部分。

Scala識別符號

  • Scala可以使用兩種形式的識別符號,字元數字和符號。
    1. 字元數字使用字母或是下劃線開頭,後面可以接字母或是數字,符號$在Scala也看最是字母,然而$開頭的識別符號為保的Scala編譯器產生的識別符號使用,應用程式應該避免使用$開始的識別符號,以免造成衝突。
    2. Scala的命名規則採用和Java的camel命名規則,首字母小寫,比如toString()。類名的首字母大寫,此外應該避免使用以下劃線結尾的識別符號以免衝突,符號識別符號包含一個或多個符號,如+m:,?等(如:+ ++ ::: < ?>:->)
  • Scala內部實現會使用轉義的識別符號,比如:->使用$colon$minus$greater來表示這個符號。因此如果你需要在java程式碼中訪問:->方法,你需要使用Scala的內部名稱$colon$minus$greater。
  • 混合識別符號由數字識別符號後面跟一個或多個符號組成,比如unary_+為Scala對+方法的內部實現時的名稱。字面量識別符號為使用"定義的字串,比如'x''yield'
  • 你可以在"之間使用任何有效的Scala識別符號,Scala將它們解釋為一個Scala識別符號,一個典型的使用為Thread的yield方法,在Scala中你不能shiyongThread.yield()是因為yield為Scala的關鍵字,你必須使用Thread.'yield'來使用這個方法

Scala的關鍵字

  • abstract、case、catch、class、def、do、else、extends、false、final、finally、for、forSome、if、implicit、import、lazy、match、new、null、object、override、package、private、protected、return、sealed、super、this、throw、trait、try、true、type、val、var、while、with、yield、-、:、=、=>、<-、<:、<%、>:、#、@

Scala註釋

  • 多行註釋
    /*
     *多行註釋
     *
     */
    
  • 單行註釋
    //單行註釋
    

空行和空格

  • 一行中只有空格或者帶有註釋,Scala會認為其是空行,會忽略它,標記可以被空格或者註釋來分割。

換行符

  • Scala是面向行的語言,語句可以用分號(;)結束或是換行符。Scala程式裡,語句末尾的分號通常是可選的如果你願意可以輸入一個,但若一行裡僅有一個語句也可不寫。另一方面,如果一行裡寫多個語句那麼分號是需要的。列入
    println("hello");println("world");
    

Scala包

  • Scala用package關鍵字定義包【兩種方式】
    1. 第一種方法和Java一樣
      package com.peng
      class HelloWord
      
    2. 第二種方法類似C#
      package com.peng{
          class HelloWorld
      }
      

引用

  • Scala使用import關鍵字引用包
    1. import java.awt.Color //引入Color
    2. import java.awt._ //引入包內所有成員
    3. import java.awt.{Color,Font} //選擇器(選擇awt包中的Color和Font工具類)
    4. import java.util.{HashMap => JavaHashMap} //重新命名成員
    5. import java.util.{HashMap => ,} //引入了util包的所有成員,但是HashMap被隱藏了

資料型別

  • Byte、Short、Int、Long、Float、Double、Char、String、Boolean、Unit【無值,和其他語言中的void等同】、Null、Nothing【Nothing型別在scala的類層級的最低端,他是任何其他型別的子型別】、Any【Any是所有其他類的超類】、AnyRef【AnyRef類是裡所有引用類(reference class)的基類】

Scala變數

  • 變數是一種使用方便的佔位符,用於引用計算機記憶體地址,變數建立之後會佔用一定的記憶體空間。基於變數的資料型別,作業系統會進行記憶體分配並且決定什麼將被保留到記憶體中,因此,通過給變數分配不同的資料型別,你可以在這些變數中儲存整數,小數或者字母。
  • 在程式執行過程中值可能發生改變的量叫做變數【在scala中,用var表示】

常量

  • 在程式執行過程中值不會發生變化的量叫做常量【在scala中,用val表示】

變數型別宣告

  • var VariableName:DataType [= Initial Value]
    • 例:var aa:String="你好,世界!";
  • 變數宣告一定需要初始值,否則會報錯
  • 變數型別引用中,不一定要指明資料的型別
    • 例:var aa="你好,世界!";
  • 多個變數的宣告
    • 例:var a,b,c=100;

Scala的修飾符

  • Scala的修飾符基本和java一樣,分別有private,protected,public
  • 如果沒有指定訪問修飾符,預設情況下Scala物件的訪問級別都是public
  • Scala中的private限定符,比java更嚴格,在巢狀類情況下,外層類甚至不能訪問被巢狀類的私有成員。
  • 在Scala中,對保護(Protected)成員的訪問相比java更嚴格一些,因為它只允許保護成員在定義了該成員的類的子類中被訪問,而在Java中,用protected關鍵字修飾的成員,除了定義了該成員的類的子類可以訪問,同一個包裡的其他類也可以進行訪問

作用域保護

  • Scala中,訪問修飾符可以通過使用限定詞強調,格式為:
    • private[x]
    • protected[x]
  • 這裡的x代表所屬的包、類或單例物件。如果寫成private[x],讀作“這個成員除了對[...]中的類或[...]中的包中的類及他們的伴生物件可見外,對其他所有的類都是private”
  • package bobsrocckets{
        package navigation{
            private[bobsrockets] class Navigator{
             protected[navigation] def useStarChart(){}
             class LegOfJourney{
                 private[Navigator] val distance = 100
                 }
                private[this] var speed = 200
                }
            }
            package launch{
            import navigation._
            object Vehicle{
            private[launch] val guide = new Navigator
            }
        }
    }
    
    //上述例子中,類Navigator被標記為private[bobsrockets],就是說這個類對包含在bobsrocckets包裡的所有的類和物件可見。
    

Scala運算子

  • 算數運算子【+ - * / %】
  • 關係運算符【== != > < >= <=】
  • 邏輯運算子【&& || !】
  • 位運算子【~ & | ^ << >> >>>】
  • 賦值運算子【= += -= *= /= %= <<= >>= &= ^= |=】

運算子的優先順序

類別 運算子 關聯性
1 ()[] 左到右
2 !~ 右到左
3 */% 左到右
4 +- 左到右
5 >> << >>> 左到右
6 > >= < <= 左到右
7 == != 左到右
8 & 左到右
9 ^ 左到右
10 左到右
11 &&
12 短路或 左到右
13 = += -= *= /= %= >>= <<= &= ^= 右到左
14 , 左到右

Scala中的三大結構

  • 選擇結構
    1. if
    2. if...else
    3. if...else if
  • 迴圈結構

    1. while
    2. do...while【至少執行一次】
    3. for

      • for(var x<- Range){
            println(x);
        }
        
        
        //迴圈10次 
        for(a <- 1 to 10){
            println(x);
        }
        

Scala方法與函式

  • Scala方法是類的一部分,而函式是一個物件可以賦值給一個變數。換句話說在類中定義的函式即是方法
  • Scala中的方法根java的類似,方法是組成類的一部分
  • Scala中的函式則是一個完整的物件,Scala中的函式其實就是繼承了Trait的類的物件
  • Scala中使用val語句可以定義函式,def語句定義方法
    • class Test{
          def m(x:Int)=x+3
          val f=(x:Int) => x+3
      }
      
  • 方法宣告格式如下
    def functionName([引數列表]):[return type]
    //注:如果你不寫等號和方法主體,那麼方法會被隱式宣告為抽象
    
  • 方法定義
    def functionName([引數列表]):[returnType]={
        function body
        return [expr]
    }
    
  • package com.peng.scala
    
    object Test {
    
      def main(args: Array[String]) {
        //呼叫
        print(add(1, 2));
      }
    
      //求和函式
      def add(a: Int, b: Int): Int = {
        var sum: Int = 0;
        sum = a + b;
        return sum;
      };
    
    }
    
  • 如果方法沒有返回值,可以返回Unit,這個類似於java的void

Scala閉包

  • 閉包是一個函式,返回值依賴在宣告在函式外部的一個或多個變數;閉包通常來講可以簡單的認為是可以訪問一個函式裡面區域性變數的另外一個函式。
  • package com.peng.scala
    
    object Test {
    
      def main(args: Array[String]) {
        print(mutiplier(2));
      }
    
      var factor = 66;
      val mutiplier = (i: Int) => i * factor;
    
    }
    

Scala字串

  • 在Scala中,字串的型別實際上是Java String,它本身沒有String類,String是一個不可變物件,所以該物件不可以被修改,這就意味著你如果修改字串就會產生一個新的字串物件。String是不可變的物件,如果建立一個需要修改的字串,可以使用String Builder
  • 建立字串
    1. var s="hello world";
    2. var s:String="hello world";
  • 字串長度length()方法
  • 字串連線concat(String)方法或直接使用+號
  • 建立格式化的字串printf函式

    • package com.peng.scala
      
      object Test {
        def main(args: Array[String]) {
          var s = printf("浮點型變數為 %f, 整型變數為 %d, 字串為 %s", 200.0, 66, 3);
          println(s)
        }
      }
      
      //執行結果
      浮點型變數為 200.000000, 整型變數為 66, 字串為 3()
      
  • 插值
    • s
      val name = “James”
      println(s “Hello, $name”) //output: Hello, James
      
    • f
      val height = 1.9d
      val name = "James"
      println(f"$name%s is $height%2.2f meters tall") //James is 1.90 meters tall
      
    • raw
      object Demo {
       def main(args: Array[String]) {
          println(raw"Result = \n a \n b")//Result = \n a \n b
       }
      }
      
  • String方法【同Java中的String方法】

Scala陣列

  • Scala語言提供的陣列是用來儲存固定大小的同類型元素
  • Scala中的陣列

    var z:Array[String]=new Array[String](2);
    
    //或
    
    var z=new Array[String](2);
    
    z(0)="z0";
    z(1)="z1";
    
  • Scala中的多維陣列

    package com.peng.scala
    
    object Test {
      def main(args: Array[String]) {
        val arr2 = Array.ofDim[String](2, 2)
        arr2(0)(0) = "aa"
        arr2(1)(0) = "bb"
        for (i <- 0 until arr2.length; j <- 0 until arr2(0).length) {
          println(arr2(i)(j))
        }
      }
    }
    
  • 合併陣列Array.concat

    package com.peng.scala
    
    object Test {
      def main(args: Array[String]) {
        var s1 = new Array[String](3);
        var s2 = new Array[String](2);
    
        s1(0) = "s11";
        s1(1) = "s12";
        s1(2) = "s13";
    
        s2(0) = "s21";
        s2(1) = "s22";
    
        var result = Array.concat(s1, s2);
    
        for (temp <- result) {
          println(temp);
        }
      }
    }
    
    //執行結果
    s11
    s12
    s13
    s21
    s22
    
  • 建立區間陣列range

    • 引數(開始,結束,步長)

      package com.peng.scala
      
      object Test {
        def main(args: Array[String]) {
          var r1 = Array.range(1, 100, 3);
          for(temp <- r1){
            print(temp+"\t");
          }
        }
      }
      
  • Scala陣列的方法
    1. apply建立
    2. concat合併
    3. copy複製
    4. empty返回長度為0的陣列
    5. iterate返回指定長度的陣列
    6. fill填充陣列
    7. ofDim建立陣列
    8. range建立分割槽陣列
    9. tabulate返回指定長度的陣列內容【預設從0開始】

Collection

  • List:特徵是其元素以線性方式儲存,集合可以存放重複物件
    • val l=List(1,2,3);
      
  • Set:Set是最簡單的一種集合,集合中的物件不按特定的方式排序,並且沒有重複物件
    • val s=Set(1,2,3);
      
  • Map:是一種把鍵物件和值物件對映的集合,它的每一個元素都包含一對鍵物件和值物件
    • val m=Map("one"->1,"two"->2);
      
  • 元組:元組是不同型別的值的集合
    • val y=(10,"hello");
      
  • Option表示有可能包含值的容器,也可能不含值
    • val o:Option[Int]=Some(5)
      
  • Iterator:迭代器,迭代器不是一個容器,更確切的說是逐一訪問容器內元素的方法

    • Iterator不是一個集合,它是一種用於訪問集合的方法
    • Iterator的兩個基本方法是next()和hasNext()
    • 呼叫it.next()會返回迭代器的下一個元素,並且更新迭代器的狀態
    • 呼叫hasNext()用於檢測集合中是否還有元素

      package com.peng.scala
      
      object Test {
        def main(args: Array[String]) {
          val it = Iterator("a", "b", "c");
          while (it.hasNext) {
            print(it.next() + "\t");
          }
        }
      }
      
      //執行結果
      a   b   c
      
    • 查詢最大、最小元素

      package com.peng.scala
      
      object Test {
        def main(args: Array[String]) {
          val it = Iterator("a", "w", "c");
          print("最大的元素為:"+it.max);
        }
      }
      
    • Iterator的長度

      package com.peng.scala
      
      object Test {
        def main(args: Array[String]) {
          val it1 = Iterator("a", "w", "c");
          val it2 = Iterator("a", "w", "c", "d");
          print("長度:" + it1.length);
          print("長度:" + it2.size);
        }
      }
      
      //執行結果
      長度:3長度:4
      
    • Iterator其他的方法【見Scala的Iterator的API】

Scala的類和物件

  • 類是物件的抽象,而物件是類的例項化,類是抽象的,不佔用記憶體,而物件是具體的,佔用儲存空間。類是用於建立物件的藍圖,它是一個定義包括在特定型別的物件中的方法和變數的軟體模板。
  • package com.peng.scala
    
    class Point(xc: Int, yc: Int) {
    
      var x: Int = xc;
      var y: Int = yc;
    
      def move(dx: Int, dy: Int) {
        x = x + dx;
        y = y + dy;
        print("x的座標為:" + x + ",y的座標為:" + y);
      }
    
    }
    
    object PointTest {
      def main(args: Array[String]) {
        val point = new Point(1, 2);
        point.move(3, 4);
      }
    }
    
  • 繼承

    1. 重寫一個非抽象方法必須使用override關鍵字
    2. 只有在主建構函式才可以往基類的建構函式裡寫引數
    3. 在子類中重寫超類的抽象方法時,你不需要使用override關鍵字
    4. package com.peng.scala
      
      class Point(xc: Int, yc: Int) {
      
        var x: Int = xc;
        var y: Int = yc;
      
        def move(dx: Int, dy: Int) {
          x = x + dx;
          y = y + dy;
          print("x的座標為:" + x + ",y的座標為:" + y);
        }
      
      }
      
      class Location(val xc: Int, val yc: Int, val zc: Int) extends Point(xc, yc) {
        var z: Int = zc;
      
        def move(dx: Int, dy: Int, dz: Int) {
          x = x + dx;
          y = y + dy;
          z = z + dz;
          print("x的座標為:" + x + ",y的座標為:" + y + ",z的座標為" + z);
        }
      
      }
      
      object PointTest {
        def main(args: Array[String]) {
          val point = new Location(1, 2, 3);
          point.move(3, 4, 5);
        }
      }
      

Scala單例物件

  • 在Scala中,是沒有static這個東西的,但是它也為我們提供了單例的實現方法,那就是使用關鍵字object,Scala中使用單例模式時,除了定義的類之外,還要定義一個同名的object物件,object物件不能帶引數。當單例物件與某個類共享同一個名稱時,他被稱作這個類的伴生物件:companion object.你必須在同一個原始檔裡定義類和它的伴生物件。類被稱為是這個單例物件的伴生類:companion class,類和它的伴生物件可以互相訪問其私有成員。
  • 單例物件例項【object】

    package com.peng.scala
    
    class Poin(val xc: Int, val yc: Int) {
    
      var x: Int = xc;
      var y: Int = yc;
    
      def move(dx: Int, dy: Int) {
        x = x + dx;
        y = y + dy;
      }
    
    }
    
    object Tes {
      def main(args: Array[String]) {
        val poin = new Poin(10, 20);
    
        printPoin
    
        def printPoin {
          poin.move(4,5);
          println("x的座標:" + poin.x);
          println("y的座標:" + poin.y);
        }
      }
    }
    
  • 伴生物件與伴生類例項

    • object和class的名稱相同,互為【伴生類或伴生物件】,在class中可以直接通過object的名稱訪問object中的物件

      package com.peng.scala
      
      object University {
        private var studentNo = 0
        def newStudentNo = {
          studentNo += 1
          studentNo
        }
      }
      
      class University {
        val id = University.newStudentNo
        private var number = 0
        def aClass(number: Int) { this.number += number }
      }
      

Scala中的Trait【特徵】

  • Scala中的Trait相當於Java中的介面,實際上它比介面的功能更加強大。與介面不同的是,它還可以定義屬性和方法的實現。
  • 一般情況下Scala的類只能夠繼承單一父類,但是如果Trait的話就可以繼承多個,從結果來看就是實現了多重繼承
  • 例子

    package com.peng.scala
    
    trait Equal {
      def isEqual(x: Any): Boolean;
      def isNotEual(x: Any): Boolean = !isEqual(x);
    }
    
    class EqualSon(xc: Int, yc: Int) extends Equal {
      var x: Int = xc;
      var y: Int = yc;
      def isEqual(obj: Any) = (obj.isInstanceOf[EqualSon]) && (obj.asInstanceOf[EqualSon].x == x);
    }
    
    object TestEual {
      def main(args: Array[String]) {
        val es23 = new EqualSon(2, 3);
        val es24 = new EqualSon(2, 4);
        val es33 = new EqualSon(3, 3);
        println("(2,3)與(2,4)的比較結果為:" + es23.isEqual(es24));
        println("(2,3)與(3,3)的比較結果為:" + es23.isEqual(es33));
      }
    }
    
    //執行結果【這裡主要是比較x的值是否相等】
    (2,3)與(2,4)的比較結果為:true
    (2,3)與(3,3)的比較結果為:false
    

特徵構造順序

  • 特徵也可以有構造器,由欄位的初始化和其他特徵體中的語句構成,這些語句在任何混入該特徵的物件在構造時都會被執行。
  • 構造器的執行順序
    1. 呼叫超類的構造器
    2. 特徵構造器在超類構造器之後、類構造器之前執行
    3. 特徵由左到右被構造
    4. 每個特徵中,父特徵先被構造【如果多個特徵共有一個特徵,父特徵不會被重複構造】
    5. 所有特徵被構造完畢,子類被構造
  • 構造器的順序是類的線性化的反向,線性化是描述某個型別的所有超型別的一種技術規格

Scala的模式匹配

  • 一個模式匹配包含了一系列備選項,每個都開始於關鍵字case。每個備選項都包含了一個模式及一到多個表示式。箭頭符號=>隔開了模式和表示式
  • package com.peng.scala
    
    object ModelCatch {
      def main(args: Array[String]) {
        println(matchTest(0));
        println(matchTest(1));
        println(matchTest(1111));
      }
    
      def matchTest(x: Int): String = x match {
        case 0 => "匹配到0"
        case 1 => "匹配到1"
        case _ => "匹配到非0,1"
      }
    
    }
    
    //執行結果
    匹配到0
    匹配到1
    匹配到非0,1
    
  • 使用樣例類

    • 使用了case關鍵字的類定義就是樣例類,樣例類是特殊的類,經過優化以用於模式匹配

      package com.peng.scala
      
      object Yll {
        def main(args: Array[String]) {
          val p1 = new PP("張三", 12);
          val p2 = new PP("李四", 13);
      
          for (person <- List(p1, p2)) {
            print("開始匹配:")
            person match {
              case PP("張三", 12) => print("【匹配到了張三】")
              case PP("李四", 13) => print("【匹配到了李四】")
            }
            print(",結束一次匹配\n")
          }
        }
      
        case class PP(name: String, age: Int);
      }
      
      //執行結果
      開始匹配:【匹配到了張三】,結束一次匹配
      開始匹配:【匹配到了李四】,結束一次匹配
      

Scala的正則表示式

  • Scala中通過scala.util.matching包的Regex類來支援正則表示式

    • package com.peng.scala
      
      import scala.util.matching.Regex;
      
      object Regextest {
        def main(args: Array[String]) {
          val pattern = new Regex("(S|s)cala\\d+") // 首字母可以是大寫 S 或小寫 s
          val str = "Scala2 Scalaa is scalable and cool"
          println((pattern findAllIn str).mkString(",")) // 使用逗號 , 連線返回結果
        }
      }
      
      //結果
      Scala2
      

Scala異常處理

  • 丟擲異常
    • Scala中的丟擲異常的方法和Java一樣,使用throw方法,例如
      throw new IllegalArgumentException
      
  • 捕獲異常

    • 在catch字句中,越具體的異常越要靠前,越普遍的異常越靠後,如果丟擲的異常不在catch中,該異常則無法處理,會升級到被呼叫者處
    • 需要注意的是:catch語法和其他語言不太一致,借用了模式匹配的思想來做異常的匹配
    • 例如

      package com.peng.scala
      
      import java.io.FileReader
      import java.io.FileNotFoundException
      import java.io.IOException
      
      object ExceptionTest {
        def main(args: Array[String]) {
          try {
            val f = new FileReader("test.txt");
          } catch {
            case ex: FileNotFoundException => {
              print("FileNotFoundException!");
            }
            case ex: IOException => {
              println("IO Exception!")
            }
            case ex: Exception => {
              println("Exception!")
            }
          } finally {
            print("\nfinal...");
          }
        }
      }
      
      
      //執行結果
      FileNotFoundException!
      final...
      
  • finally語句
    • 不管是正常處理還是異常發生都正常執行

Scala提取器

  • 提取器是從傳遞給它的物件中提取出構造該物件的引數。Scala標準庫包含了一些預定義的提取器,,Scala提取器是一個帶有unapply方法的物件,unapply方法算是apply方法的相反的操作:unapply接受一個物件,然後從物件中提取值,提取的值通常是用來構造該物件的值。
  • package com.peng.scala
    
    object UnapplyTest {
    
      def main(args: Array[String]) {
        println("Apply 方法 : " + apply("Zara", "gmail.com"));
        println("Unapply 方法 : " + unapply("[email protected]"));
        println("Unapply 方法 : " + unapply("Zara Ali"));
    
      }
    
      //注入方法(可選)
      def apply(user: String, domain: String) = {
        user + "@" + domain;
      }
    
      //提取方法(必選)
      def unapply(str: String): Option[(String, String)] = {
        var parts = str split "@"
    
        if (parts.length == 2) {
          Some(parts(0), parts(1))
        } else {
          None
        }
    
      }
    
    }
    
    //執行結果
    Apply 方法 : [email protected]
    Unapply 方法 : Some((Zara,gmail.com))
    Unapply 方法 : None
    
  • unapply方法算是apply方法的方法的反向操作,unapply接受一個物件,然後從物件中提取值,提取的值通常是用來構造該物件的值。
    • unapply("[email protected]")相當於Some("Zara","gmail.com")
    • unapply("Zara Ali")相當於None
  • 提取器使用模式匹配

    • 我們在例項化一個類時,可以帶上0或多個引數,編譯器在例項化的時候會呼叫apply方法,我們可以在類和物件中部定義apply方法,就想之前提過的unapply方法,當我們在提取器中使用match語句時,unapply將自動執行
    • package com.peng.scala
      
      object CaseUnapplyTest {
        def main(args: Array[String]) {
          val x = CaseUnapplyTest(5);
      
          println(x);
      
          x match {
            case CaseUnapplyTest(num) => print(x + "是" + num + "的兩倍")
            //unapply 被呼叫
            case _                    => println("無法計算")
          }
      
        }
      
        def apply(x: Int) = { x * 2 };
        def unapply(z: Int): Option[Int] = {
          if (z % 2 == 0) {
            Some(z / 2);
          } else {
            None
          }
        }
      }
      
  • apply方法有點類似java中的建構函式,接受構造引數變成一個物件;unapply方法剛好相反,它是接受一個物件,從物件中提取值。

Scala中I/O操作

  • Scala中進行檔案寫操作,直接用的是java中的I/O類
  • 例,檔案的寫入操作

    package com.peng.scala
    
    import java.io.PrintWriter
    import java.io.File
    
    object IoTest {
      def main(args: Array[String]) {
        val writer = new PrintWriter(new File("io_test.txt"));
        writer.write("hello world!");
        writer.close();
      }
    }
    
  • 執行結果

  • 從螢幕上讀取使用者輸入

    • package com.peng.scala
      
      import scala.io.StdIn
      
      object StdIntest {
        def main(args: Array[String]) {
          println("下面可以進行輸入:");
          val line = StdIn.readLine();
          println("您輸入的資料是:" + line);
        }
      }
      
      //執行結果
      下面可以進行輸入:
      hello world!
      您輸入的資料是:hello world!
      
  • 從檔案中讀取資料

    • 從檔案中讀取資料非常簡單,我們可以使用Scala的Source類及伴生物件來讀取檔案
    • package com.peng.scala
      
      import scala.io.Source
      
      object FileReadTest {
        def main(args: Array[String]) {
          println("檔案的內容為:");
          Source.fromFile("io_test.txt").foreach { print }
        }
      }
      
      //執行結果
      檔案的內容為:
      hello world!
      

隱性類

  • 當類在範圍內時,隱式類允許與類的主建構函式進行隱式通話。隱式類是一個標有‘impicit’關鍵字的類,此功能在Scala2.10中引入。
  • 語法(以下是隱式類的語法,這裡,隱式類始終位於物件範圍內,所有方法定義都被允許 ,因為隱式類不能是頂級類) object