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"字串。*/ } }