Scala(一)資料型別
Scala
Scala簡介
Scala 是一種基於 JVM 的多正規化程式語言,這裡的正規化可以理解為一種程式設計 風格,比如物件導向程式設計就是一種正規化。常見正規化包括:程式導向、物件導向、 泛型以及函數語言程式設計。
一、Scala特點
1.1 靜態型別
Scala的變數宣告後不允許改變型別
,換句話說所有的變數和表示式在編譯時就已經完全確定。這一點和Java是一樣的。- 可以增強IDE的型別感知能力,適大型複雜系統開發
感知就是在使用的時候,就能夠去獲取它的型別 - 可讀性好,可以宣告時指定型別,且使用前必須確定型別
1.2 強型別
Scala是強型別語言
,一個變數被指定了某個人資料型別,如果不經過強制轉換,name它就永遠是這個資料型別,也就是說不允許隱式型別轉換。意味著 Scala 是型別安全的語言,這點和 Java 也相同,但 Scala 在宣告變數時一般無需顯示指 定型別,Scala 編譯器會自動推斷出型別
Scala沒有提供Java中的強制型別轉換,取代方法有:
①、物件名.asInstanceOf[XXX]
②、物件名.toXXX 方法
③、隱式轉換(implicit 關鍵字)
1.3 物件導向程式設計(OOP)
Scala 中一切值都是物件,可以說 Scala 比 Java OOP 更純粹。比如,Java 中類 物件(包含靜態欄位和方法)便不是純粹的物件,因為類是一個抽象的概念,對 象是類的例項,是一個具體的概念。所以 Scala 中去除了 static 關鍵字,使用一 種特殊的物件來模擬類物件(伴生物件),使得類的所有靜態內容都可以放置在 它的伴生物件中宣告和呼叫。
二、伴生物件
伴生物件
package one
// 建構函式建立:變數在前,型別在後,自動對映到類裡變成屬性
class Scala_Basic(name:String,age:Int){
// 方法 變數寫在類裡
def show():Unit={
println(s"my name is $name, I'm $age") // 格式化
}
}
// 伴生物件(有同名類)
object Scala_Basic {
def main(args: Array[String]): Unit = {
// 為了把常量區分開,放在Object中,也體現了動靜分離
// 建立變數的方式
var a = new Test("henrry",18)
a.show() // 呼叫方法
}
}
=> my name is henrry, I'm 18
三、Scala關鍵字
Java 與 Scala 關鍵字對比:
四、Scala變數和常量
val:定義常量(value)
var:定義變數(variable)
區別:val定義的引數是,不能被再次賦值,而var定義的引數可以被再次賦值。一般不嚴格說明時,變數和常量也統稱為變數。變數是可變變數,而常量是 不可變變數。
示例程式碼:
var
val
package one
object Review {
def main(args: Array[String]): Unit = {
val a = 18
println(a)
var b = 10
println(b)
println("--------")
//這裡如果寫上a=10重新賦值會直接報錯,執行不了
//a=10 這裡是寫寫不了的,直接會報錯
println(a)
b = 20
println(b)
}
}
可以看出val定義的常量a不能被改變,而var定義的變數b重新賦值後值改變了
變數的建立方式
在scala中,數值型別為一類型別(包括八大型別)
// 可以不指定型別,但是一定要賦值
var a = 1
var b:Int = 2
// 正確宣告變數的方式
var a = 1
var b:Int = 2
var c:String = "henrry"
var g:Char = '男'
var s:Double = 80.0
var d:Int = _ // 沒有值得時候可以給個下劃線:_
val e:Int = _ // 這個時候就會報錯,常量必須初始化
五、Scala資料型別
- 整體上分為兩類:
值型別(AnyVal)
和引用型別(AnyRef)
,超級父類為Any
,超級子類為Nothing
。 - 值型別和Java八大基本型別一致(byte、short、int、long、float、double、char、boolean),
注意在Scala中所有型別首字母都大寫
,還有一個Unit型別,類似於Java中的void,除 了 scala.Unit 和 scala.Boolean 外其餘都是數字型別。 - 所有的非值型別都是引用型別,,如果 Scala 執行中 Java 環境中,AnyRef 相當於 java.lang.Object。特別地,Scala 中的 String 型別等同於 java.lang.String。
- 值型別:直接儲存值,在棧上儲存其值。
- 引用型別:儲存對其值得引用,在棧上儲存地址,在堆上儲存值。
- ==是值比較,eq(b)為地址比較
5.1 Unit
Unit 代表沒有任何意義的值型別,他是 AnyVal 的子型別,僅有一個例項對 象“()”,叫做無用佔位符,類似於 Java 中的 void 型別。
結構圖
一般來說用map較多
package two
object Test {
def main(args: Array[String]): Unit = {
var map = Map("henrry" -> 18, "areiel" -> 20, "pola" -> 14)
map.keys.foreach(println)
}
}
=> henrry
areiel
pola
陣列
package two
object Test {
def main(args: Array[String]): Unit = {
var arr = Array(11,2,33,42,14)
// 模擬陣列下標,用下標做一個陣列
var ixArr = Range.apply(0,arr.length)
arr.foreach(x=>print(s"$x\t"))
println()
ixArr.foreach(x=>print(s"$x\t"))
}
}
=>輸出結果
11 2 33 42 14
0 1 2 3 4
六、Scala字串插值(拼接)
Scala 為我們提供了三種字串插值的方式,分別是 s, f 和 raw
。其本質都 是定義在 StringContext 中的方法
。
① # s 利用之後學習的隱式轉換實現
// $符號可以理解為引用值
val name = "henrry"
println(s"my name is $name")
=> my name is henrry
println(s"1 and 1 eq ${1+1}")
=> 1 and 1 eq 2
或者可以這麼寫,宣告瞭變數型別(可寫可不寫)
在Scala中宣告變數和常量不一定要指明資料型別,在沒有指明資料型別的情況下,其資料型別是通過變數或常量的初始值推斷出來的。但是一定要賦初值
var x:Int = 2
println(x)
=> 2
② # f 簡單格式化
var name = "henrry";var age = 19;var score=88.123;var gender = '男'
println(f"name=$name%s,age=$age%d,score=$score%.2f,gender=$gender%c")
=> name=henrry,age=19,score=88.12,gender=男
③ # raw 即所見所得,不轉義
println(s"a\tb\nc\td")
println("------")
println(raw"a\tb\nc\td")
=> a b
c d
------
a\tb\nc\td
④、模式匹配
var score = 88
var rst = score.match {
// i就是score,是隱式引數傳進來的
case i if i>=80 =>"A"
case i if i>=70 =>"B"
case i if i>=60 =>"C"
case i =>"D" // 相當於default
println(rst)
}
=> 輸出結果 A
字串
var line:String = """"""
var s = 'Abc // 符號變數
println(s.isInstanceOf[scala.Symbol])
=>true
Null
- 型別Null只有一個物件(Java中null不是物件)
- 所有引用型別的子類
Nothing
- 所有型別子類,也是Null的子類
Unit
- 無意義的值型別
- 類似於Java中的void
- 在scala中有返回值(),scala中一切表示式都有值
七、函式的定義
- 函式的定義以def開始,然後是函式名,類似於 def main
- 跟著的是括號裡使用逗號分隔的引數型別鍵值對,類似x:Int,y:Int
- 下面的程式碼表示maxInt函式帶有兩個引數:x和y,都是Int型別,在函式列表後,會使用"返回值型別="的形式宣告函式的返回值型別,我的理解是,
一切函式都是值
,最後的肯定是一個值,如果需要返回值,則需要用返回型別接收確認返回值。
定義格式:
def functionName ([引數列表]) : [return type] = {
function body
}
def maxInt(x:Int) = {
if(x > y) x else y
}
// 呼叫函式
val m = maxInt(6,9)
println(m)
=> 9
函式
函式有23種,由trait定義
package one
object Process2 {
// 簡潔的寫函式
val func = (x: Int, y: Int) => {
x + y
// 最後一句話是什麼,返回值就是什麼,沒有return
}
// 完整的去寫一個函式
val fun2 = new Function2[Int, Double, Double] { // 泛型 ,輸出型別為Double型
override def apply(v1: Int, v2: Double): Double = v1 + v2
}
def main(args: Array[String]): Unit = {
println(func(1,2))
println(fun2(1,2))
}
}
=> 輸出都為3
型別轉換
Boolean a = obj.instanceOf[Xxx]
Xxx a = Obj.asInstanceOf[Xxx]
obj.toXxx
隱式轉換(implicit Xxx)
package one
object Process2 {
}
def main(args: Array[String]): Unit = {
var a : String = "henrry"
println(a.isInstanceOf[String]) // isInstance:判斷是不是指定型別
=>返回true
println(a.isInstanceOf[Int])
=>返回false
// 嘗試轉換型別
var a : String = "henrry"
println(a.isInstanceOf[String])
if(a.asInstanceOf[Boolean]){
println("ok")
}
//這裡執行會直接報錯,不給轉,也因此證明了scala是強型別
}
// 建立一個陣列
var arr:Array[Int] = Array(1,5,3,2)
println(arr.toList)
=> List(1, 5, 3, 2)
println(arr.toString)
=> [I@6bdf28bb
println(arr.toSet)
=> Set(1, 5, 3, 2)
// 萬物皆可to,直接轉換
}
建立一個函式
一切函式都為值
可以將函式作為引數和返回值
object Process2 {
val fun2 = new Function2[Int, Double, Double] {
override def apply(v1: Int, v2: Double): Double = v1 + v2
}
def main(args: Array[String]): Unit = {
// 定義一個方法
def add(x:Doubele,y:Int):Double = {
println(s"$x + $y = ${x+y}")
x + y
}
println(add(fun2(1,2)),3) 先呼叫fun2的方法,得到一個結果,再將這個結果作為add方法的輸入最終得到一個結果
=> 輸出6.0
3.0 + 3 = 6.0
6.0
// 驗證了一切函式都為值
}
}
八、程式控制
8.1 條件控制(重點if)
var b : Int = 5
var a = if(b>5) "a" else 2.0
=> 2.0
val x = 9
val y = if(x==10) x+1
println(y )
=> ()
如果說if後面沒有else,則預設else部分的值是Unit,返回()
8.2 塊表示式{}
也是一個結果,{}中最後一行的結構就是快表示式的結果
var a = {
var a =6;var b = 5;
a*b
}
println(a)
=> 30
#賦值語句的結果為Unit
var x = 10
var y = {
x = x * 2
//x*2
}
println()
=> ()
// 建立程式碼塊時即建立了一個作用域,在程式碼塊內可以訪問程式碼塊外的實體 (變數、函式、類),反之不成立。因為最後一個是表示式,不是值,輸出為Unit,但是當我加上了x*2後,一切都是值,這個時候就可以列印值40
九、for迴圈
9.1 單迴圈
迴圈
// 迴圈
// 像陣列但不是陣列,如果要轉為陣列,直接在後面.toArray
var arr = Range.apply(1,10,2) // 2代表的是步幅為2
for (elem <- arr) {
println(elem)
}
// 更為簡潔的一種方式
for (elem <- 1 until 10 by 2) {
println(elem)
}
=>輸出結果為 1 3 5 7 9
for (i <- 表示式) {
statements
}
- 首先,
變數 i 不需要宣告
。嚴格來說是 i 前面不允許有 val 或 var。i 可以是作 用域內的現有變數。
- 其次“<-”是關鍵字,非操作符,類似 Java 中的“:”。
- 最後表示式可以是陣列、元組、集合。在 Scala 中 Range 是常用的集合型別, 表示範圍區間。
Range min to/until max by step :指的是從最小值到最大值,步長為多少
to與until的區別:to是到多少,可以取到最大值,until是直到多少,取不到最大值
案例:
for (i <- 0 to 10 by 2 if i % 3 == 0) {
println(i)
}
// 首先從0 2 4 6 8 10中選擇,可以理解為這是第一個函式的值,然後作為下一個函式的輸入,篩選符合取模3等於0的數,最後篩選出 0 6
=> 0 6
for (i <- 0 to 10 by 2 if i % 3 == 0 if i > 5) {
println(i)
}
=> 6
// 首先根據上面的程式碼可以知道,篩選出0,6 再作為最後一個函式的入口引數,最後可以得到6
9.2 多重迴圈
for (i <- 表示式1;j <- 表示式2;....){
statements
}
案例:
for (i <- 1 to 20 if i % 2 == 0; j <- 1 to i if j % 3 == 0) {
println(s"$i\t$j")
}
=>4 3 部分結果
6 3
6 6
8 3
for (elem <- 1 to 100;if elem%7==0;if elem%3==0) { // ;兩個條件都要滿足
println(elem)
}
=> 21 42 63 84
// 小九九
#注意:如果()中有多個表示式,可以使用{}代替,換行寫多條語句
for {i <- 1 to 20 if i % 2 == 0
j<-1 to 20 if j%3==0}{
println(s"$i\t$j")
}
十、迴圈跳轉語句
scala中沒有break和continue,需要手動導包
//scala中沒有break,continue 需要手動導包
import scala.util.control.Breaks._ // ._相當於.*
breakable {
for (elem <- 1 to 100) {
println(elem)
if (elem%17==0){
break()
}
}
}
#推導式
十一、資料結構
在 Scala 中,物件一般都有兩種方式建立,一種使用類建立,一種使用其對 應的伴生物件建立,區別在於是否使用 new 關鍵字。本章暫不涉及 OOP 的內容, 瞭解伴生物件建立的方式即可。
Scala資料結構是非常重要的知識點,並且Scala中的資料結構遠比Java豐富、 複雜。但是基本原理都是相同的,比如說陣列、棧、佇列、連結串列、樹、雜湊表。 這裡主要關注線性結構,包括 Array、Seq、List、Map 及 Set 等。
對 比 Java , Scala 中 的 數 據 結 構 都 強 調 了 是 可 變 還 是 不 可 變 , 即 mutable/immutable,預設情況下,Scala 會為使用者選擇不可變的資料結構。兩者 的差別在於:
不可變:初始化後內容不再發生變化。
可變:初始化後內容可以發生變化。
十二 、陣列
相關文章
- scala和java資料型別轉換Java資料型別
- 一、資料型別資料型別
- 【Scala之旅】型別引數型別
- scala資料結構(一)資料結構
- js資料型別之基本資料型別和引用資料型別JS資料型別
- 資料型別: 資料型別有哪些?資料型別
- Java 資料型別和 MySql 資料型別對應一覽表JavaMySQL 資料型別
- 區別值型別資料和引用型別資料型別
- TypeScript學習(一)—— 資料型別TypeScript資料型別
- 資料型別,型別轉換資料型別
- 資料型別資料型別
- 【Scala之旅】特質與高階型別型別
- JAVA中基本資料型別和引用資料型別Java資料型別
- 3. php資料型別、資料型別轉換PHP資料型別
- 基本資料型別與字串型別資料型別字串
- 關於 PHP 的資料型別 (一)PHP資料型別
- 前端基礎(一):js資料型別前端JS資料型別
- JavaScript 基礎 (一) - 基本資料型別JavaScript資料型別
- 建立一種新的資料型別資料型別
- 重溫手冊(一):資料型別資料型別
- MySQL基礎之----資料型別篇(常用資料型別)MySql資料型別
- Java中的基本資料型別與引用資料型別Java資料型別
- Hive(一)資料型別以及DDL資料定義Hive資料型別
- Redis基礎(一)資料結構與資料型別Redis資料結構資料型別
- JavaScript - 資料型別JavaScript資料型別
- Symbol資料型別Symbol資料型別
- 資料型別2資料型別
- JavaScript 資料型別JavaScript資料型別
- js資料型別JS資料型別
- TypeScript資料型別TypeScript資料型別
- Oracle 資料型別Oracle資料型別
- SQL 資料型別SQL資料型別
- NumPy 資料型別資料型別
- php資料型別PHP資料型別
- numpy資料型別資料型別
- JavaScript資料型別JavaScript資料型別
- [Mysql]資料型別MySql資料型別
- MySQL資料型別MySql資料型別