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

猜你喜欢

转载自blog.csdn.net/yangshaojun1992/article/details/80540216