Scala - 03 - 基础语法

Posted anliven

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala - 03 - 基础语法相关的知识,希望对你有一定的参考价值。

  • 1- 变量

    变量 mutable variable
    • 在程序运行过程中其值可能发生改变的量
    • 关键词var定义变量,定义时直接进行求值
    常量 immutable variable
    • 在程序运行过程中其值不会发生变化的量
    • 在声明时就必须被初始化,而且一旦初始化后就不能再赋值;
    • 关键词val定义常量,定义时直接进行求值;
    • 关键词lazy val --- 惰性求值的常量,只有当该变量第一次被使用时才会被求值
    • 常量不能修改。如果程序尝试修改常量的值,将会在编译时报错
    变量类型引用
    • 可以不显示指定变量的类型,Scala具有“类型推断”能力,会自动进行类型推导;
    • 如果在没有指明数据类型的情况下声明变量或常量,必须要给出其初始值,否则将会报错;
    • 一般情况下,如果定义的变量可能不会被用到,可以定义该变量为lazy val;
      val myStr = "Hello Scala!"                      //> myStr  : String = Hello Scala!
      val myStr2: String = "Hello Scala!"             //> myStr2  : String = Hello Scala!
    

    示例-1:

    scala> val x = 10  # 定义常量x
    x: Int = 10  # Scala自动推导出x的类型是Int
    
    scala> val y:Int =20  # 显示定义Int类型常量
    y: Int = 20
    
    scala> x + x  # 定义表达式
    res0: Int = 20  # res0是Scala的REPL自动为没有变量名的表达式设置默认变量名,res是result的简写,0是默认变量的标号
    
    scala> res0  # 直接引用表达式res0
    res1: Int = 20  # 因为res0这个表达式没有变量名,所以REPL默认设置res1作为res0表达式结果的变量名
    
    scala> res0*res1
    res2: Int = 400
    
    scala> val z=res0+res1+res2  # 为表达式指定变量名
    z: Int = 440
    
    scala> z = 100  # 为Z赋新值
    <console>:12: error: reassignment to val  # 常量Z的值不可以被改变
           z = 100
             ^
    
    scala> var a = 200  # 定义变量a
    a: Int = 200
    
    scala> a = 300  # 可以为变量a赋新值
    a: Int = 300
    
    scala> val d = 20
    d: Int = 20
    
    scala> val e = 30
    e: Int = 30
    
    scala> lazy val f = d * e  # 定义惰性常量f
    f: Int = <lazy>  # f的值没有立即求解,<lazy>是惰性的标记
    
    scala> f*10  # 当惰性常量第一次被使用时才会被求值
    res3: Int = 6000
    
    scala> f
    res4: Int = 600
    
    scala>
    
    示例-2:
    • Scala 支持多个变量的声明
    • 如果方法返回值是元组,可以使用 val 来声明一个元组
      val x, y = 100                                  //> x  : Int = 100
                                                      //| y  : Int = 100
    
      val test = (50, "demo")                         //> test  : (Int, String) = (50,demo)
    

    2- 数据类型

    技术分享图片

    • 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           表示无值,用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。
    • Null            null 或空引用,是每个引用类(继承自AnyRef的类)的子类
    • Nothing      任何其他类型的子类型,不包括无值
     
    • Any            所有其他类的超类
    • AnyRef       Scala里所有引用类(reference class)的基类

     

    2.1-字面量

    字面量包括整数、浮点数、布尔型、字符、字符串、符号、函数和元组字面量。
    Scala允许对“字面量”直接执行方法。
      val t = 123 //123就是整数字面量                        //> t  : Int = 123
      val t2 = 3.14 //3.14就是浮点数字面量                    //> t2  : Double = 3.14
      val t3 = true //true就是布尔型字面量                    //> t3  : Boolean = true
      val t4 = ‘A‘ //‘A‘就是字符字面量                       //> t4  : Char = A
      val t5 = "Hello" //"Hello"就是字符串字面量              //> t5  : String = Hello
    
      "abc".intersect("bcd")                          //> res0: String = bc
    

    注意:intersect()方法用来输出两个字符串中都存在的字符

    2.2-数字类型

    包括Byte、Short、Int、Long、Folat、Double,其中Float、Double浮点数。
    低精度数字类型向高精度赋值时,不需要类型转换;高精度数字类型向低精度赋值时,需要类型转换。
    scala> val a:Byte = 10
    a: Byte = 10
    
    scala> val b:Short = 20
    b: Short = 20
    
    scala> val c:Int = 30
    c: Int = 30
    
    scala> val d:Long = 40
    d: Long = 40
    
    scala> val e:Float = 50
    e: Float = 50.0
    
    scala> val f:Double = 60.98765
    f: Double = 60.98765
    
    scala> val x:Long = b  # Short类型常量b赋值给Long类型常量x,低精度赋值给高精度
    x: Long = 20
    
    scala> val y:Byte = x  # Long类型常量x赋值给Byte类型常量y,高精度赋值给低精度
    <console>:12: error: type mismatch;  # 提示类型不匹配
     found   : Long
     required: Byte
           val y:Byte = x
                        ^
    
    scala>
    

    2.3-布尔类型

    scala> val m=true
    m: Boolean = true
    
    scala> val n=false
    n: Boolean = false
    
    scala>
    

    2.3-Unit

    unit多作为函数的返回值出现,在函数式编程中表示函数是有副作用的,函数不返回任何的值
    scala> val u:Unit = ()  # 显式声明Unit类型常量,()是文字量
    u: Unit = ()
    
    scala> val p=()
    p: Unit = ()
    
    scala>
    

    2.4-Null和Nothing

    Scala.Null和Scala.Nothing是用统一的方式处理某些"边界情况"的特殊类型。
    • Null表示一个引用类型的值是空,在Scala中通常不使用Null,而是使用??
    • Nothing表示程序异常终止,如果函数返回值是Nothing,表明函数发生了异常。
    scala> def foo() = throw new Exception("error occurred")
    foo: ()Nothing
    
    scala>
    

    2.5-字符

    字符表示:在半角单引号(‘)中的单个字符
    scala> ‘a‘
    res0: Char = a
    
    scala> ‘
    ‘
    res1: Char =
    
    
    scala> ‘	‘
    res2: Char =
    
    scala> ‘test‘
    <console>:1: error: unclosed character literal (or use " for string literal "test")
           ‘test‘
                ^
    
    scala>
    

    2.6-字符串

    String类型全称是java.lang.String,构建于Java的String之上,新增了字符串插值(interpolation)的特性。
    也就是说,Scala的字符串是由Java的String类来实现的,也可以使用java.lang.String来声明。
    默认情况下,Scala总会引入 java.lang._ 、 scala._ 和 Predef._,因此这里只需要使用String就可以声明变量。
      val myStr = "Hello Scala!"                      //> myStr  : String = Hello Scala!
      val myStr2: String = "Hello Scala!"             //> myStr2  : String = Hello Scala!
      val myStr3 : java.lang.String = "Hello Scala!"  //> myStr3  : String = Hello Scala!
    
    • 单行字符串表示:在双引号(") 中包含的单行字符
    • 多行字符串表示:在三个双引号(""")中包含的多行字符。
    scala> val myname = "Anliven"
    myname: String = Anliven
    
    scala> s"My name is ${myname}"
    res0: String = My name is Anliven
    
    scala> """row 1
         | row 2
         | row 3"""
    res1: String =
    row 1
    row 2
    row 3
    
    scala>
    

    3- 打印语句

    • print语句:不换行打印
    • println语句:每次打印后追加一个换行符,实现换行的效果
    • printf函数:C语言风格格式化字符串
      print("This is a ")                             //> This is a 
      print("test!")                                  //> test!
      println("This is a test!")                      //> This is a test!
    
      val test = 123456                               //> test  : Int = 123456
      println(test)                                   //> 123456
      printf("My name is %s, the ID is %d.
    ", "Anliven", test)
                                                      //> My name is Anliven, the ID is 123456.
    

    4- 操作符

    在Scala中,可以使用加(+)、减(-) 、乘(*) 、除(/) 、余数(%)等操作符。
    也可以使用大于(>)、小于(<)、大于等于(>=)和小于等于(<=)等关系和逻辑操作符,产生Boolean类型结果。
    操作符本身就是方法,“a 方法 b”是“a.方法(b)”的简写形式,两者是等价的。
      val Sum1 = 6 + 2                                //> Sum1  : Int = 8
      val Sum2 = (6).+(2)                             //> Sum2  : Int = 8
    

    在Scala中并没有提供“++”和“--”操作符,但可以“+=”方式来实现自增或自减

      var test = 1                                    //> test  : Int = 1
      test += 1
      println(test)                                   //> 2
    

    注意:使用“+=”方式时,要使用var声明变量,否则执行时会报错。

    5- 常见转义字符

    技术分享图片

    0 到 255 间的 Unicode 字符可以用一个八进制转义序列来表示,即反斜线??后跟 最多三个八进制。

      println("Hello World
    
    Hello Scala");          //> Hello World
                                                      //| 
                                                      //| Hello Scala
    

    6- Range

    Range可以支持创建不同数据类型的数值序列,包括Int、Long、Float、Double、Char、BigInt和BigDecimal等。
    在创建Range时,需要给出区间的起点和终点以及步长(默认步长为1)。
      1 to 3                                          //> res0: scala.collection.immutable.Range.Inclusive = Range 1 to 3
      1.to(3)                                         //> res1: scala.collection.immutable.Range.Inclusive = Range 1 to 3
      1 until 3                                       //> res2: scala.collection.immutable.Range = Range 1 until 3
      1 to 10 by 3                                    //> res3: scala.collection.immutable.Range = Range 1 to 10 by 3
      0.5f to 5.9f by 0.8f                            //> res4: scala.collection.immutable.NumericRange[Float] = NumericRange 0.5 to 5.
                                                      //| 9 by 0.8
    

    7- 代码块(code block)

    • 在Scala中,代码块(code block)用于组织多个表达式。
    • 代码块也是一个表达式,其最终求得的值是最后一个表达式的值。
    • 只有一个表达式的代码块,花括号是可以省略的。
    scala> var x = 10
    x: Int = 10
    
    scala> var y = 20
    y: Int = 20
    
    scala> x + y
    res0: Int = 30
    
    scala> {x*2;y*2;x*y}  # 代码块也是一个表达式,其最终求得的值是最后一个表达式的值。
    res1: Int = 200
    
    scala> {
         | x + y
         | x + x + y + y
         | }
    res2: Int = 60
    
    scala>
    

    8- 函数

    • 函数是一组一起执行一个任务的语句。
    • 逻辑上,每个函数执行一个特定的任务。
    • 定义函数最常用的方法是作为某个对象的成员,这种函数被称为方法。
    • 方法是类的一部分,而函数是一个对象可以赋值给一个变量。
    方法定义
    Scala 函数定义格式如下:
    def functionName ([参数列表]) : [return type] = {
       function body
       return [expr]
    }
    
    解释说明:
    • def 关键字声明函数定义,函数名functionName遵守命名规范
    • 可选的[参数列表],参数列表中的参数可以使用逗号分隔
    • 冒号":" 后是方法的返回类型[return type],可以是任意合法的 Scala 数据类型
    • 等于号"="后是方法的主体{}
    • function body:函数主体代码
    • return [expr]:返回值
      def hello(name: String): String = {
        s"hello, ${name}"
      }                                               //> hello: (name: String)String
      hello("Anliven")                                //> res0: String = hello, Anliven
    
      def hello2(name: String) = {
        s"hello, ${name}"
      }                                               //> hello2: (name: String)String
      hello2("Anliven")                               //> res1: String = hello, Anliven
    
      def add(x: Int, y: Int) = x + y                 //> add: (x: Int, y: Int)Int
      add (1,2)                                       //> res2: Int = 3
    

    9- if表达式

    if 语句
    • if是表达式而不是语句。
    • 如果布尔表达式为 true 则执行大括号内的语句块,否则跳过大括号内的语句块,执行大括号之后的语句块。
    • if语句可以采用各种嵌套的形式。
    • Scala中的if表达式的值可以赋值给变量
    if(布尔表达式)
    {
       // 如果布尔表达式为 true 则执行该语句块
    }
    
    if...else 语句
    if 语句后可以紧跟 else 语句,else 内的语句块可以在布尔表达式为 false 的时候执行。
    if(布尔表达式){
       // 如果布尔表达式为 true 则执行该语句块
    }else{
       // 如果布尔表达式为 false 则执行该语句块
    }
    

    一些示例:

      if (true) 1 else 2                              //> res0: Int = 1
      if (true) 3 else 4                              //> res1: Int = 3
    
      val a = 1                                       //> a  : Int = 1
      if (a == 1) a                                   //> res2: AnyVal = 1
      if (a != 1) "not one"                           //> res3: Any = ()  # 表达式不返回值,结果就是Unit的文字量(),
      if (a != 1) "not one" else a                    //> res4: Any = 1
    
    scala> val x = 6
    x: Int = 6
    
    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
    if (x>0) {println("This is a positive number")
    } else {
        println("This is not a positive number")
    }
    
    // Exiting paste mode, now interpreting.
    
    This is a positive number
    
    scala>
    
    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
    if (x>0) {
        println("This is a positive number")
    } else if (x==0) {
        println("This is a zero")
    } else {
        println("This is a negative number")
    }
    
    // Exiting paste mode, now interpreting.
    
    This is a positive number
    
    scala>
    
    scala> val test = if (x>0) 1 else -1
    test: Int = 1
    
    scala>
    

    10- 循环

    10.1-while循环

    Scala中也有while和do-while循环语句。
      var x = 3                                       //> x  : Int = 3
      while (x > 0) {
        x -= 1
        printf("i is %d
    ", x)
      }                                               //> i is 2
                                                      //| i is 1
                                                      //| i is 0
      
      var y = 0                                       //> y  : Int = 0
      do {
        y += 1
        println(y)
      } while (y < 3)                                 //> 1
                                                      //| 2
                                                      //| 3
    

    10.2-for循环

    语句格式:
    for (变量<-表达式) 语句块  // 其中,“变量<-表达式”被称为生成器(generator)
    
    for推导式:
    • 带有yield关键字的for循环。
    • 通过for循环遍历一个或多个集合,对集合中的元素进行“推导”,从而计算得到新的集合,用于后续的其他处理。
    示例-1:
      for (i <- 1 to 3) println(i)                    //> 1
                                                      //| 2
                                                      //| 3
      for (i <- 1 to 3 by 2) println(i)               //> 1
                                                      //| 3
      for (i <- 1 to 3 if i % 2 == 0) println(i)      //> 2
      for (i <- 1 to 3; j <- 1 to 3) println(i * j)   //> 1
                                                      //| 2
                                                      //| 3
                                                      //| 2
                                                      //| 4
                                                      //| 6
                                                      //| 3
                                                      //| 6
                                                      //| 9
      for (i <- 1 to 3 if i % 2 == 0; j <- 1 to 3 if j != i) println(i * j)
                                                      //> 2
                                                      //| 6
      for (i <- 1 to 5 if i % 2 == 0) yield i         //> res0: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4)
    
    注意:
    • 语句中“<-”表示,之前的i要遍历后面1到5的所有值。
    • 使用“守卫(guard)”的表达式可以满足特定条件的结果。
    • 支持“多个生成器”,可以用分号隔开。
    • 采用yield关键字,对过滤后的结果构建一个集合。
    示例-2:
      val test = List("Aaaa", "Bbb", "Cccc")          //> test  : List[String] = List(Aaaa, Bbb, Cccc)
    
      for (
        demo <- test
      ) println(demo)                                 //> Aaaa
                                                      //| Bbb
                                                      //| Cccc
      
      for {
        demo <- test
        if (demo.length > 3)
      } println(demo)                                 //> Aaaa
                                                      //| Cccc
    
      val result_for = for {
        demo <- test
        demo1 = demo.toUpperCase()
        if (demo1 != "")
      } yield (demo1)                                 //> result_for  : List[String] = List(AAAA, BBB, CCCC)
    

    11- try表达式

    • try在Scala里不是语句,而是一个表达式,会返回值。
    • 下划线“_”是通配符,可以统配所有的对象。
    • 无论是否发生异常,总会执行finally里的代码。
    object first {
      val result_try = try {
        Integer.parseInt("dog")
      } catch {
        case _: Throwable => 0
      } finally {
        println("always be printed")
      }                                               //> always be printed
                                                      //| result_try  : Int = 0
    }
    

    12- match表达式

    类似Java里的switch。
    object first {
      val code = 3                                    //> code  : Int = 3
      val result_match = code match {
        case 1 => "one"
        case 2 => "two"
        case _ => "others"
      }                                               //> result_match  : String = others
    }
    

    13- 读写文件

    写入文本文件
    示例:在当前用户的工作目录新生成的output.txt文件,并逐行添加数字1到5
    package helloscala
    import java.io.PrintWriter
    
    object helloscala {
      def main(args: Array[String]) {
        val out = new PrintWriter("output.txt")
        for (i <- 1 to 5) out.println(i)
        out.close()
      }
    }
    
    读取文本文件中的行
    使用Scala.io.Source的getLines方法实现对文件中所有行的读取。
    
    package helloscala
    import scala.io.Source
    
    object helloscala {
      def main(args: Array[String]) {
        val inputFile = Source.fromFile("output.txt")
        val lines = inputFile.getLines
        for (line <- lines) println(line)
        inputFile.close()
      }
    }
    

      


  • 以上是关于Scala - 03 - 基础语法的主要内容,如果未能解决你的问题,请参考以下文章

    Scala 基础语法

    scala语法基础1

    Scala简介及基础语法

    Scala-Unit-2-Scala基础语法1

    Scala语言专题

    Scala常用基础语法总结