1. 程式人生 > >scala開發快速入門 | 第二篇 變數及基本資料型別

scala開發快速入門 | 第二篇 變數及基本資料型別

一、宣告值和變數

Scala中有兩種型別的變數。

一種是val,是不可變的,在宣告時就必須被初始化,而且初始化以後就不能再賦值;另一種是var,是可變的,宣告的時候需要進行初始化,初始化以後還可以再次對其賦值。

Note:在專案的開發中建議使用val 也就是常量。避免資料被隨意地更改。

val變數

scala> val myStr = "Hello World!"
myStr: String = Hello World!

Scala具有“型別推斷”能力,可以自動推斷出變數的型別。

當然,我們也可以顯式宣告變數的型別:

scala>  val myStr2 : String = "Hello World!"
myStr2: String = Hello World!

需要說明的是,上面的String型別全稱是java.lang.String,也就是說,Scala的字串是由Java的String類來實現的,因此,我們也可以使用java.lang.String來宣告,具體如下:

scala> val myStr3 : java.lang.String = "Hello World!"
myStr3: String = Hello World!

但是,為什麼可以不用java.lang.String,而只需要使用String就可以宣告變數呢?這是因為,在每個應用程式中,Scala都會自動新增一些引用,這樣,就相當於在每個程式原始檔的頂端都增加了一行下面的程式碼:

import java.lang._ //java.lang包裡面所有的東西

因為myStr是val變數,因此,一旦初始化以後,就不能再次賦值,所以,下面我們執行的再次賦值操作會報錯:

scala> myStr = "Hello Scala!"
<console>:8: error: reassignment to val
       myStr = "Hello Scala!"
             ^

var變數

如果一些變數,需要在初始化以後還要不斷修改它的值(比如商品價格),則需要宣告為var變數。下面我們把myPrice宣告為var變數,並且在宣告的時候需要進行初始化:

scala>  var myPrice : Double = 9.9
myPrice: Double = 9.9

然後,我們可以再次對myPrice進行賦值:

scala> myPrice = 10.6
myPrice: Double = 10.6

注意:

1)不管是val型別的變數還是var型別的變數 在宣告的時候都要進行初始化,否則報錯

2)var宣告的變數可以使用佔位符 “_”進行初始化;String 型別使用 "_"進行初始化時變數為null;Int 、Float、Double、等基本型別使用“_”被初始化為0;

  Char 型別使用“_”被初始化為?

3)可以使用lazy關鍵字來修飾 val宣告的變數 表示只有這個變數真正被使用的時候才去賦值。

 

二、基本資料型別和操作

Scala中共有九種基本型別的資料

Byte      8位、

Short    16位

Int        32位

Long    64位

Float    32位

Double  64位

Char      

String

Boolean  

Scala的基本資料型別和java的基本資料型別一 一對應 不同的是Java的基本資料型別首字母不需要大寫,Scala的首字母必須大寫,這是因為Scala中所有的值型別都是物件。    

基本型別操作

Scala語言是純面向物件程式語言,在Scala中一切皆物件,所有的操作都是方法的呼叫。

1)算數運算子操作

在Scala中,可以使用加(+)、減(-) 、乘(*) 、除(/) 、餘數(%)等操作符,而且,與java不同的是這些操作符都是方法。例如,5 + 3和(5).+(3)是等價的,也就是說:

a 方法 b
a.方法(b)

上面這二者是等價的。前者是後者的簡寫形式,這裡的+是方法名,是Int類中的一個方法。具體程式碼如下:

scala> val sum1 = 5 + 3
sum1: Int = 8
scala> val sum2 = (5).+(3)
sum2: Int = 8

需要注意的是,和Java不同,在Scala中並沒有提供++和- -操作符,當需要遞增和遞減時,可以採用如下方式表達:

scala> var i = 5;
i: Int = 5
scala>  i += 1
scala> println(i)
6

2)關係運算操作

大於(>)、小於(<)、大於等於(>=)和小於等於(<=),會產生Boolean型別的結果。

3)邏輯運算操作

&& 和 ||

4)位運算操作

位與(&) 、位或(|)、位異或(^)、取反(~)、左移位(<<)、右移位(>>)、無符號左移位(<<<)、無符號右移位(>>>)

//整型 3對應的二進位制:           000000000  0000000000  00000000  00000011

//整型 5對應的二進位制:           000000000  0000000000  00000000  00000101

//位與(&)操作後的二進位制: 000000000  0000000000  00000000  00000001

scala>3 & 5

res25: Int = 1

//整型 3對應的二進位制:           000000000  0000000000  00000000  00000011

//整型 5對應的二進位制:           000000000  0000000000  00000000  00000101

//位或(|)操作後的二進位制:   000000000  0000000000  00000000  00000111

scala>3 | 5

res26: Int = 7

//整型 3對應的二進位制:                000000000  0000000000  00000000  00000011

//整型 5對應的二進位制:                000000000  0000000000  00000000  00000101

//位異或(^)操作後的二進位制:   000000000  0000000000  00000000  00000110

scala>3 ^ 5

res27: Int = 6

//整型 3對應的二進位制:   000000000  0000000000  00000000   00000011

//取反操作後的二進位制:   11111111    11111111      11111111   11111100

scala>~3 

res28: Int = -4

//整型 6對應的二進位制:   000000000  0000000000  00000000  00000110

//左移一位:                   000000000  0000000000  00000000  00001100

scala>6<<1

res29: Int = 12

//整型 6對應的二進位制:   000000000  0000000000  00000000  00000110

//右移一位:                   000000000  0000000000  00000000  00000011

scala>6>>1

res30: Int = 3

//無符號右移:    11111111  11111111  11111111 11111111

//移動後的結果: 000000000  0000000000  00000000  00000001

scala>-1>>31

res31: Int = 1

5)物件比較運算操作

Scala中物件的比較和java中物件的比較不同,Scala是基於內容進行比較的,而java是比較的物件的引用,即:比較的是實體記憶體地址是否一樣。

6)字串運算操作

Scala中的String型別實際上就是java中的String的型別,因此可以呼叫java 中String型別的所有方法。

三、運算子優先順序

四、元組型別

1)元組是Scala中特殊的型別,元組是不同型別值的聚集,它可以將不同型別的值放在一個變數中進行儲存。

scala>var tuple=("hello","China",1)

tuple: (String, String, Int) = (hello,China,1)

2)訪問元組的內容,通過 變數名._N的方式,其中N代表元組中元素的索引號,從1開始。

scala> tuple._1

res14: String = hello

3)在使用的時候還可以將元組的內容進行提取,對變數進行初始化。

scala> val (first,second,third)=tuple
first: String = hello
second: String = China
third: Int = 1
scala> println(first)

hello

4)對應元組使用== 進行比較的時候實際上比較的是元組中對應索引號的內容。

scala> var tuple=("hello","China",1)
tuple: (String, String, Int) = (hello,China,1)

scala> var tuple2=("hello","China",1)
tuple2: (String, String, Int) = (hello,China,1)

scala> tuple==tuple2
res16: Boolean = true

scala> var tuple3=("hello",1,"China")
tuple3: (String, Int, String) = (hello,1,China)

scala> tuple==tuple3
res17: Boolean = false

五、符號型別

1)Symbol是Scala中常用的一種符號型別,符號型別的定義需要使用 ’符號。

//使用 ’定義符號型別的變數,scala型別推斷為Symbol型別

scala> val s='start
s: Symbol = 'start
//明確指定是符號型別

scala> val s1:Symbol= 'stop
s1: Symbol = 'stop

符號型別主要起標識的作用,在模式匹配、內容的判斷中比較常用。

scala> if(s1=='start) println("start.....") else println("other...............")

other...............

2)符號型別的變數在輸出的時候會按照原樣輸出

scala> println(s1)

'stop

3)與String型別、元組型別等變數一樣,使用==符號進行變數比較,比較的是變數的內容而不是引用。

scala> val s2='start
s2: Symbol = 'start

scala> val s3='start
s3: Symbol = 'start

scala> s2==s3
res20: Boolean = true

偏函式

/*偏函式
* 1)概念
*   Scala中的Partia Function是一個Trait,其的型別為PartialFunction[A,B],其中接收一個型別為A的引數,返回一個型別為B的結果。
*   偏函式之所以“偏”,原因在於它們並不處理所有可能的輸入,而只處理那些能與至少一個case 語句匹配的輸入。
* 2)在偏函式中只能使用case 語句,而整個函式必須用花括號{}包圍
* 3)如果偏函式被呼叫,而函式的輸入卻與所有語句都不匹配,系統就會丟擲一個MatchError執行時錯誤。
* 4)偏函式內部有一些方法,比如isDefinedAt、OrElse、 andThen、applyOrElse等。
*   isDefinedAt:判斷傳入來的引數是否在這個偏函式所處理的範圍內。
*/
object PartialFunction {

  def main(args: Array[String]): Unit = {

    val pf1: PartialFunction[Int, String] = {
      case 1 => "One"
      case 2 => "Two"
      case 3 => "Three"
      case _ => "Other"
    }
    println(pf1(1)) //One
    println(pf1(2)) //Two
    println(pf1(4)) //Other

    val pf2: PartialFunction[Int, String] = {
      case 1 => "One"
      case 2 => "Two"
      case 3 => "Three"
    }
    //    println(pf2(4)) //MatchError 錯誤

    /*常用方法
    * 1)isDefinedAt 判斷傳入的引數是否在這個偏函式處理的範圍內
    *   剛才定義的pf來嘗試使用isDefinedAt(),只要是數字都是正確的,因為有case _=>"Other"這一句。
    *   如果換成其他型別就會報錯。*/
    pf1.isDefinedAt(1) //true
    //    pf1.isDefinedAt("2")
    pf2.isDefinedAt(4) //flase
    if (pf2.isDefinedAt(4)) {
      println(pf2(4))

    }
    /*2)orElse : 將多個偏函式組合起來使用,效果類似case語句*/
    val onePF: PartialFunction[Int, String] = {
      case 1 => "One"
    }
    val twoPF: PartialFunction[Int, String] = {
      case 2 => "Two"
    }
    val threePF: PartialFunction[Int, String] = {
      case 3 => "Three"
    }
    val otherPF: PartialFunction[Int, String] = {
      case _ => "Other"
    }
    //    將多個偏函式連線
    val newPF = onePF orElse twoPF orElse threePF orElse otherPF
    newPF(3)
    /*3)andThen: 相當於方法的連續呼叫,比如g(f(x))。*/

    val pf3: PartialFunction[Int, String] = {
      case i if i == 1 => "One"
    }

    val pf4: PartialFunction[String, String] = {
      case str if str == "One" => "The number is 1"
    }
    val num = pf3 andThen pf4
    println(num(1)) //pf3的結果返回型別必須和pf4的引數傳入型別必須一致,否則會報錯。

    /*4)applyOrElse:它接收2個引數,第一個是呼叫的引數,第二個是個回撥函式。如果第一個呼叫的引數匹配,返回匹配的值,否則呼叫回撥函式。*/
    onePF.applyOrElse(1, { num: Int => "two" })
    onePF.applyOrElse(2, { num: Int => "two" })
    /*在這個例子中,第一次onePF匹配了1成功則返回的是"One"字串。第二次onePF匹配2失敗則觸發回撥函式,返回的是"Two"字串。*/
  }
}