Scala學習之路 (三)Scala的基本使用


一、Scala概述

scala是一門多范式編程語言,集成了面向對象編程和函數式編程等多種特性。
scala運行在虛擬機上,並兼容現有的Java程序。
Scala源代碼被編譯成java字節碼,所以運行在JVM上,並可以調用現有的Java類庫。

二、第一個Scala程序

Scala語句末尾的分號可寫可不寫

HelloSpark.scala

object HelloSpark{
    def main(args:Array[String]):Unit = {
        println("Hello Spark!")
    }
}

運行過程需要先進行編譯

編譯之后生成2個文件

運行HelloSpark.class

輸出結果Hello Spark

三、Scala的基本語法

1、概述

/**
  * Scala基本語法:
  * 區分大小寫
  * 類名首字母大寫(MyFirstScalaClass)
  * 方法名稱第一個字母小寫(myMethodName())
  * 程序文件名應該與對象名稱完全匹配
  * def main(args:Array[String]):scala程序從main方法開始處理,程序的入口。
  *
  * Scala注釋:分為多行/**/和單行//
  *
  * 換行符:Scala是面向行的語言,語句可以用分號(;)結束或換行符(println())
  *
  * 定義包有兩種方法:
  *   1、package com.ahu
  *      class HelloScala
  *   2、package com.ahu{
  *       class HelloScala
  *     }
  *
  * 引用:import java.awt.Color
  * 如果想要引入包中的幾個成員,可以用selector(選取器):
  *   import java.awt.{Color,Font}
  *   // 重命名成員
  *   import java.util.{HashMap => JavaHashMap}
  *   // 隱藏成員 默認情況下,Scala 總會引入 java.lang._ 、 scala._ 和 Predef._,所以在使用時都是省去scala.的
  *   import java.util.{HashMap => _, _} //引入了util包所有成員,但HashMap被隱藏了
  */

2、Scala的數據類型

Scala 與 Java有着相同的數據類型,下表列出了 Scala 支持的數據類型:

數據類型 描述
Byte 8位有符號補碼整數。數值區間為 -128 到 127
Short 16位有符號補碼整數。數值區間為 -32768 到 32767
Int 32位有符號補碼整數。數值區間為 -2147483648 到 2147483647
Long 64位有符號補碼整數。數值區間為 -9223372036854775808 到 9223372036854775807
Float 32位IEEE754單精度浮點數
Double 64位IEEE754單精度浮點數
Char 16位無符號Unicode字符, 區間值為 U+0000 到 U+FFFF
String 字符序列
Boolean true或false
Unit 表示無值,和其他語言中void等同。用作不返回任何結果的方法的結果類型。Unit只有一個實例值,寫成()。
Null null 或空引用
Nothing Nothing類型在Scala的類層級的最低端;它是任何其他類型的子類型。
Any Any是所有其他類的超類
AnyRef AnyRef類是Scala里所有引用類(reference class)的基類

 Scala多行字符串的表示方式

var str =
      """
        |第一行
        |第二行
        |第三行
      """.stripMargin
    println(str)

3、Scala的變量

object VariableTest {
  def main(args: Array[String]) {
    //使用val定義的變量值是不可變的,相當於java里用final修飾的變量
    val i = 1
    //使用var定義的變量是可變的,在Scala中鼓勵使用val
    var s = "hello"
    //Scala編譯器會自動推斷變量的類型,必要的時候可以指定類型
    //變量名在前,類型在后
    val str: String = "world"
  }
}

總結:

1)數據類型可以指定,也可以不指定,如果不指定,那么就會進行數據類型的推斷。

2)如果指定數據類型,數據類型的執行 方式是 在變量名后面寫一個冒號,然后寫上數據類型。

3)我們的scala里面變量的修飾符一共有兩個,一個是var 一個是val,如果是var修飾的變量,那么這個變量的值是可以修改的。如果是val修飾的變量,那么這個變量的值是不可以修改的。

4、Scala訪問修飾符

Scala訪問修飾符和Java基本一樣,分別有private、protected、public。

默認情況下,Scala對象的訪問級別是public。

(1)私有成員

用private關鍵字修飾的成員僅在包含了成員定義的類或對象內部可見。

class Outer {
  class Inner{
    def start() = println("start")
    def end() = println("end")
    private def pause() = println("pause")
  }

  new Inner().start()
  new Inner().end()
  new Inner().pause()

}

在上面的代碼里start和end兩個方法被定義為public類型,可以通過任意Inner實例訪問;pause被顯示定義為private,這樣就不能在Inner類外部訪問它。執行這段代碼,就會如注釋處聲明的一樣,會在該處報錯:

(2)protected

和私有成員類似,Scala的訪問控制比Java來說也是稍顯嚴格些。在 Scala中,由protected定義的成員只能由定義該成員和其派生類型訪問。而在 Java中,由protected定義的成員可以由同一個包中的其它類型訪問。在Scala中,可以通過其它方式來實現這種功能。

package p
{
    class Super
    {
        protected def f(){println("f")}
    }

    class Sub extends Super
    {
        f() //OK
    }

    class Other
    {
        (new Super).f() //Error:f不可訪問
    }
}

 

(3)public

public訪問控制為Scala定義的缺省方式,所有沒有使用private和 protected修飾的成員(定義的類和方法)都是“公開的”,這樣的成員可以在任何地方被訪問。Scala不需要使用public來指定“公開訪問”修飾符。

注意:Scala中定義的類和方法默認都是public的,但在類中聲明的屬性默認是private的。

(4)作用保護域

作用域保護:Scala中,訪問修飾符可以通過使用限定詞強調。
private[x] 或者 protected[x]
private[x]:這個成員除了對[...]中的類或[...]中的包中的類及他們的伴生對象可見外,對其他的類都是private。

package bobsrockets
{
    package navigation
    {
        //如果為private class Navigator,則類Navigator只會對當前包navigation中所有類型可見。
        //即private默認省略了[X],X為當前包或者當前類或者當前單例對象。
        //private[bobsrockets]則表示將類Navigator從當前包擴展到對bobsrockets包中的所有類型可見。
        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 val guide:表示guide默認被當前單例對象可見。
            //private[launch] val guide:表示guide由默認對當前單例對象可見擴展到對launch包中的所有類型可見。
            private[launch] val guide = new Navigator
        }
    }
}

 

在這個例子中,類Navigator使用 private[bobsrockets] 來修飾,這表示這個類可以被bobsrockets包中所有類型訪問,比如通常情況下 Vehicle無法訪問私有類型Navigator,但使用包作用域之后,Vechile 中可以訪問Navigator。

5、Scala運算符

與Java一樣,不過Scala的運算符實際上是一種方法。

6、條件表達式

Scala的的條件表達式比較簡潔,例如:

def main(args: Array[String]): Unit = {
    val x = 1
    //判斷x的值,將結果賦給y
    val y = if (x > 0) 1 else -1
    //打印y的值
    println("y=" + y)

    //支持混合類型表達式
    val z = if (x > 1) 1 else "error"
    //打印z的值
    println("z=" + z)

    //如果缺失else,相當於if (x > 2) 1 else ()
    val m = if (x > 2) 1
    println("m=" + m)

    //在scala中每個表達式都有值,scala中有個Unit類,寫做(),相當於Java中的void
    val n = if (x > 2) 1 else ()
    println("n=" + n)

    //if和else if
    val k = if (x < 0) 0
    else if (x >= 1) 1 else -1
    println("k=" + k)
  }

運行結果

總結:

1)if條件表達式它是有返回值的

2)返回值會根據條件表達式的情況會進行自動的數據類型的推斷。

7、塊表達式

 def main(args: Array[String]): Unit = {
    val x = 0
    val result = {
      if(x < 0)
        1
      else if(x >= 1)
        -1
      else
        "error"
    }
    println(result)
  }

運行結果

8、循環

(1)while循環

  def main(args: Array[String]): Unit = {
    var n = 10
    while ( {
      n > 0
    }) {
      println(n)
      n -= 1
    }
  }

總結:

1)while使用跟java一模一樣

2)注意點:在scala里面不支持 i++  i-- 等操作

統一寫成 i-=1

(2)for循環 

在scala中有for循環和while循環,用for循環比較多

for循環語法結構:

for (i <- 表達式/數組/集合)

def main(args: Array[String]): Unit = {
    //for(i <- 表達式),表達式1 to 10返回一個Range(區間)
    //每次循環將區間中的一個值賦給i
    for (i <- 1 to 10)
      print(i+"\t")

    //for(i <- 數組)
    println()
    val arr = Array("a", "b", "c")
    for (i <- arr)
      println(i)

    //高級for循環
    //每個生成器都可以帶一個條件,注意:if前面沒有分號
    for(i <- 1 to 3; j <- 1 to 3 if i != j)
      print((10 * i + j) + " ")
    println()

    //for推導式:如果for循環的循環體以yield開始,則該循環會構建出一個集合
    //每次迭代生成集合中的一個值
    val v = for (i <- 1 to 10) yield i * 10
    println(v)

  }

運行結果

總結:

  1)在scala里面沒有運算符,都有的符號其實都是方法。

  2)在scala里面沒有++  -- 的用法

  3)for( i  <-  表達式/數組/集合)

  4)在for循環里面我們是可以添加if表達式

  5)有兩個特殊表達式需要了解:

     To  1 to 3   1 2 3

     Until  1 until 3  12

  6)如果在使用for循環的時候,for循環的時候我們需要獲取,我們可以是使用yield關鍵字。

9、方法和函數

(1)定義方法

方法的返回值類型可以不寫,編譯器可以自動推斷出來,但是對於遞歸函數,必須指定返回類型。

如果不寫等號,代表沒有返回值。

(2)定義函數

(3)方法和函數的區別

在函數式編程語言中,函數是“頭等公民”,它可以像任何其他數據類型一樣被傳遞和操作

案例:首先定義一個方法,再定義一個函數,然后將函數傳遞到方法里面

object TestScala {
  //定義一個方法
  //方法m2參數要求是一個函數,函數的參數必須是兩個Int類型
  //返回值類型也是Int類型
  def m1(f:(Int,Int) => Int) : Int = {
    f(2,6)
  }
  //定義一個函數f1,參數是兩個Int類型,返回值是一個Int類型
  val f1 = (x:Int,y:Int) => x+y
  //再定義一個函數f2
  val f2 = (m:Int,n:Int) => m*n
  //main方法
  def main(args: Array[String]): Unit = {
    //調用m1方法,並傳入f1函數
    val r1 = m1(f1)
    println("r1="+r1)
    //調用m1方法,並傳入f2函數
    val r2 = m1(f2)
    println("r2="+r2)
  }
}

(4)將方法轉換成函數

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM