zoukankan      html  css  js  c++  java
  • Scala基本语法

    [toc]

    ## Scala变量

    > 不论是使用哪种高级程序语言编写程序,变量都是其程序的基本组成单位。

    ### 1. 变量的快速入门

    > 1. 变量相当于内存中一个数据存储空间的表示,你可以把变量看做是一个房间的门牌号,通过门牌号我们可以找到房间,而通过变量名可以访问到变量(值)。
    > 2. 声明/定义变量(`scala要求变量声明时初始化`),然后使用它
    > 3. Scala变量快速入门代码如下:

    ~~~~scala
    /**
    * @Date 2021/3/21 16:38
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ScalaVarDemo01 {
    def main(args: Array[String]): Unit = {
    var a: Int = 10
    var b: Int = 20
    b = 30;
    println("a=" + a)
    println("b=" + b)

    var age: Int = 10
    var sal: Double = 11.2
    var name: String = "tom"
    var isPass: Boolean = true

    // 在Scala中,小数默认为Double,整数默认为Int
    var score : Float = 99.99F
    println(s"$name 今年 $age 岁了 ,薪资为$sal 绩效为 $score 是否涨工资 $isPass")
    }
    }
    ~~~~

    #### 变量的使用说明:

    ~~~scala
    // 基本语法:
    var | val 变量名 [: 变量类型] = 变量值
    ~~~

    > 1. 声明变量时,类型可以省略(编译器自动推导,即类型推导)
    > 2. 类型确定后,就不能修改,说明Scala是强数据类型语言(同Java)
    > 3. 在声明/定义一个变量时,可以使用var或者 val来修饰, var修饰的变量可改变,val修饰的变量不可改。
    > 4. val修饰的变量在编译后,等同于加上 final。
    > 5. var 修饰的对象引用可以改变,val修饰的则不可改变,但对象的状态(值)却是可以改变的。(比如:自定义对象、数组、集合等等)
    > 6. 变量声明时,需要初始值。

    ~~~~scala
    /**
    * @Date 2021/3/21 17:17
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ScalaVarDemo02 {
    def main(args: Array[String]): Unit = {

    // 类型推导,这个时候age是Int类型
    var age = 18

    /**
    * 有两种方式我们可以age是Int类型的:
    * 1. idea提示
    * 2. println(age.isInstanceOf[Int]) 结果为true
    */

    // 类型确定后,就不能修改,说明Scala是强数据类型语言
    // age = 2.1 编译器报错

    // age可以修改,因为age是var声明的
    age = 19
    val sal = 200
    // sal是val声明的,所以不可变
    // sal = 10000 编译器报错

    /**
    * Scala设计者为什么设计 var 和 val 呢?
    * 1、在实际编程,我们更多的需求是获取/创建一个对象后,读取该对象的属性,或者是修改对象的属性值,但是我们很少去改变这个对象本身。
    * var dog = new Dog()
    * dog.age = 99
    * dog = new Dog()
    * 这时我们就可以使用val定义dog
    * val dog = new Dog()
    * dog.age = 99
    * 2、因为val 没有线程安全问题,因此效率高,scala的设计者推荐我们val
    * 3、如果对象需要改变,则使用var
    */
    val dog = new Dog()
    // 0
    println(dog.age)

    println(dog.name)

    // 这里我们就不能有下面的操作了
    // dog = new Dog()

    }
    }

    /**
    * 声明一个Dog类
    */
    class Dog {
    // 声明一个age属性,给了一个默认值 _
    var age: Int = _
    var name: String = "小花"
    }
    ~~~~

    #### 程序中 + 的使用:

    > 1. 当左右两边都是数值型时,则做加法运算
    > 2. 当左右两边有一方为字符串,则做拼接运算

    ### 2. Scala数据类型

    > 1. Scala 与Java有着相同的数据类型,==在Scala中数据类型都是对象==,也就是说scala没有java中的原生类型
    > 2. Scala数据类型分为两大类AnyVal(值类型)和 AnyRef(引用类型),注意:不管是AnyVal还是AnyRef都是对象。
    > 3. 相对于java的类型系统,Scala要复杂些!`也正是这复杂多变的类型系统才让面向对象编程和函数式编程完美的融合在了一起。`

    ~~~~scala
    /**
    * @Date 2021/3/21 18:48
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ScalaTypeDemo01 {
    def main(args: Array[String]): Unit = {

    var num: Int = 10

    /*
    因为Int是一个类,因此他的一个实例,就是可以使用很多方法
    在 scala中,如果一个方法,没有形参,则可以省略()
    */
    println(num.toDouble + "\n" + num.toString + "\n" + 10.toString)

    var isPass = true
    println(isPass.toString)

    // 这两种方法的调用都可以
    sayHi()
    sayHi
    }

    def sayHi(): Unit = {
    println("say hi~")
    }

    }
    ~~~~

    #### Scala 数据类型体系一览图

    ![image-20210321215931328](assets/image-20210321215931328.png)

    >对上面图的小结和整理
    >
    >1. 在Scala中有一个根类型Any ,他是所有类的父类。
    >2. Scala中一切皆为对象,分为两大类AnyVal(值类型),AnyRef(引用类型),他们都是Any子类
    >3. Null类型是Scala 的特别类型,它只有一个值null,他是 bottom class ,是所有AnyRef 类型的子类。
    >4. Nothing类型也是bottom class ,他是所有类的子类,在开发中通常可以将Nothing类型的值返回给任意变量或者函数,这里抛出异常使用很多。
    >5. 在Scala中仍然遵守,低精度的值,向高精度的值自动转换(implicit conversion)隐式转换。

    ~~~~scala
    /**
    * @Date 2021/3/21 19:04
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ScalaTypeDemo02 {
    def main(args: Array[String]): Unit = {

    // 默认为double
    var num1 = 1.2
    var num2 = 1.7f
    //在scala中仍然遵守,低精度的值,向高精度的值自动转换(implicit conversion)隐式转换

    //num2 = num1,错误
    num2 = num2.toFloat
    println(num2)

    //false
    println(num2.isInstanceOf[Double])
    // true
    println(num2.isInstanceOf[Float])

    println(sayHello)
    }

    /**
    * 比如开发中,我们有一个方法,就会异常中断,这时就可以返回Nothing
    * 即当我们Nothing 做返回值,就是明确说明该方法有没有正常返回值
    * @return Nothing
    */
    def sayHello: Nothing = {
    throw new Exception("抛出异常")
    }
    }
    ~~~~

    #### Scala数据类型列表

    ![image-20210321220419588](assets/image-20210321220419588.png)

    ##### 整数类型

    Scala 的整数类型就是用于存放整数值的,比如 12, 30,3456等等。

    ![image-20210321220850758](assets/image-20210321220850758.png)

    > 整形的使用细节:
    >
    > 1. Scala各整数类型有固定的表数范围和字段长度,不受具体OS的影响,以保证Scala程序的可移植性。
    > 2. Scala的整型 常量/字面量 默认为 Int 型,声明Long型 常量/字面量 须后`加‘l’或‘L’`
    > 3. Scala程序中变量常声明为Int型,除非不足以表示大数,才使用Long

    ~~~scala
    /**
    * @Date 2021/3/21 19:31
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ScalaTypeDemo03 {
    def main(args: Array[String]): Unit = {
    println("Int的最大值:" + Int.MaxValue)
    println("Int的最小值:" + Int.MinValue)
    println("Long的最大值:" + Long.MaxValue)
    println("Long的最小值:" + Long.MinValue)

    var i = 10
    var j = 10L

    // 报错,因为超过了Int的范围
    //var k = 9223372036854775807
    }
    }
    ~~~

    ##### 浮点类型

    Scala的浮点类型可以表示一个小数,`比如 123.4f,7.8 ,0.12等等。`

    ![image-20210321221525093](assets/image-20210321221525093.png)

    > 浮点数的使用细节:
    >
    > 1. 与整数类型类似,Scala 浮点类型也有固定的表数范围和字段长度,不受具体OS的影响。
    >
    > 2. Scala的浮点型常量默认为Double型,声明Float型常量,须后`加‘f’或‘F’`。
    >
    > 3. 浮点型常量有两种表示形式:
    >
    > ~~~~scala
    > 十进制数形式:如:5.12 512.0f .512 (必须有小数点)
    > 科学计数法形式:如:5.12e2 = 5.12乘以10的2次方 5.12E-2 = 5.12除以10的2次方
    > ~~~~
    >
    > 4. 通常情况下,应该使用Double型,因为它比Float型更精确

    ~~~~scala
    /**
    * @Date 2021/3/21 19:31
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ScalaTypeDemo03 {
    def main(args: Array[String]): Unit = {
    var num1: Float = 2.2345678910f
    var num2: Double = 2.2345678910

    /**
    * num1=2.2345679
    * num2=2.234567891
    */
    println("num1=" + num1)
    println("num2=" + num2)
    }
    }
    ~~~~

    ##### 字符类型

    字符类型可以表示单个字符,字符类型是Char, 16位无符号Unicode字符(2个字节),`区间值为 U+0000 到 U+FFFF`

    ~~~scala
    /**
    * @Date 2021/3/21 19:46
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ScalaCharDemo {
    def main(args: Array[String]): Unit = {

    var char1: Char = 97

    /** 当我们输出一个char类型,
    * 他会输出该数字对应的字符(码值表unicode)/unicode码值表包括ascii
    */

    // char1 = a
    println("char1 = " + char1)

    // char可以当做数字进行运行
    var char2: Char = 'a'
    var num = 10 + char2
    // num = 107
    println("num = " + num)

    /**
    * 原因和分析:
    * 1、当把一个计算的结果赋值一个变量,则编译器会进行类型转换及判断(即会看范围+类型)
    * 2、当把一个字面量赋值一个变量,则编译器会进行范围的判定
    */
    //var c2: Char = 'a' + 1
    //var c3: Char = 97 + 1
    var c4: Char = 98
    // c4 = b
    println("c4 = " + c4)
    }
    }
    ~~~

    > 字符类型使用细节:
    >
    > 1. 字符常量是用单引号(‘ ’)括起来的单个字符。例如:`var c1 = 'a‘ var c2 = '中‘ var c3 = '9'`
    >
    > 2. Scala 也允许使用`转义字符‘\’`来将其后的字符转变为特殊字符型常量。例如:`var c3 = ‘\n’`
    >
    > ![image-20210321222643375](assets/image-20210321222643375.png)
    >
    > 3. 可以直接给Char赋一个整数,然后输出时,会按照对应的 `unicode` 字符输出。
    >
    > 4. Char类型是可以进行运算的,相当于一个整数,因为它都对应有Unicode码.
    >
    > 5. 字符型 存储到 计算机中,需要将字符对应的码值(整数)找出来
    >
    > 1. 存储:字符——>码值——>二进制——>存储
    > 2. 读取:二进制——>码值——> 字符——>读取
    >
    > 6. 字符和码值的对应关系是通过字符编码表决定的(是规定好), 这一点和Java一样。

    ##### 布尔类型

    > 1. 布尔类型也叫Boolean类型,Booolean类型数据只允许取值true和false
    > 2. boolean类型占1个字节。
    > 3. boolean 类型适于逻辑运算,一般用于程序流程控制:
    > 1. if条件控制语句;
    > 2. while循环控制语句;
    > 3. do-while循环控制语句;
    > 4. for循环控制语句

    ##### Unit类型、Null类型和Nothing类型

    ![image-20210321223344072](assets/image-20210321223344072.png)

    > 使用细节和注意事项:
    >
    > 1. Null类只有一个实例对象,null,类似于Java中的null引用。null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal:比如 Int, Float, Char, Boolean, Long, Double, Byte, Short)
    > 2. Unit类型用来标识过程,也就是没有明确返回值的函数。由此可见,Unit类似于Java里的void。Unit只有一个实例,`()`,这个实例也没有实质的意义
    > 3. Nothing,可以作为没有正常返回值的方法的返回类型,非常直观的告诉你这个方法不会正常返回,而且由于Nothing是其他任意类型的子类,他还能跟要求返回值的方法兼容。

    ~~~~scala
    /**
    * @Date 2021/3/21 20:06
    * @Version 10.21
    * @Author DuanChaojie
    */
    object UnitNullNothingDemo {
    def main(args: Array[String]): Unit = {
    val res = sayHello()
    // res = ()
    println("res = " + res)

    /**
    * Null类只有一个实例对象,null类似于Java中的null引用
    * null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal:比如 Int, Float, Char, Boolean, Long,Double, Byte, Short)
    */
    val dog: Dog = null
    println("ok1~~~")
    //val char: Char = null 运行会报错
    println("ok1~~~")

    }

    /**
    * Unit等于Java的void,只有一个实例值()
    */
    def sayHello(): Unit = {

    }
    }

    class Dog {

    }
    ~~~~

    ### 3.值类型转换

    > 1. 当Scala程序在进行赋值或者运算时,`精度小的类型自动转换为精度大的数据类型`,这个就是自动类型转换(隐式转换)。
    >
    > 2. 数据类型按精度(容量)大小排序为:
    >
    > ![image-20210322135731500](assets/image-20210322135731500.png)

    #### 值类型隐式转换

    > 1. 有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。 5.6 + 10 = >double
    > 2. 当我们把精度(容量)大的数据类型赋值给精度(容量)小 的数据类型时,就会报错,反之就会进行自动类型转换。
    > 3. `(byte, short) 和 char之间不会相互自动转换。`
    > 4. byte,short,char 他们三者可以计算,在计算时首先转换为int类型。
    > 5. 自动提升原则: 表达式结果的类型自动提升为操作数中最大的类型。

    ~~~~scala
    /**
    * @Date 2021/3/22 14:09
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ScalaDataConvertDemo01 {
    def main(args: Array[String]): Unit = {
    var n1 = 10
    var n2 = 1.1f
    /**
    * 有多种类型的数据混合运算时,
    * 系统首先自动将所有数据转换成容量最大的那种数据类型,
    * 然后再进行计算
    * n3是Float类型的
    */
    var n3 = n1 + n2

    //(byte, short) 和 char之间不会相互自动转换。
    var n4: Byte = 10
    //var char1: Char = n4 ,报错,因为byte不能自动转换char
    }
    }
    ~~~~

    #### 高级隐式转换和隐式函数

    Scala还提供了非常强大的隐式转换机制(隐式函数,隐式类等等),我们放在高级部分专门用一个章节来讲解。

    #### 强制类型转换

    > 1. `自动类型转换的逆过程`,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转函数,但可能造成精度降低或溢出,格外要注意。
    >
    > 2. 特别注意:
    >
    > ~~~~scala
    > java
    > int num = (int)2.5
    > scala
    > var num : Int = 2.7.toInt //对象
    > ~~~~
    >
    > 3. 强制类型转换细节说明:
    >
    > 1. 当进行数据的 从 大——>小,就需要使用到强制转换
    > 2. 强转符号只针对于`最近的操作数有效`,往往会`使用小括号提升优先级`
    > 3. `Char类型可以保存 Int的常量值,但不能保存Int的变量值,需要强转`
    > 4. Byte和Short类型在进行运算时,当做Int类型处理。

    ~~~~scala
    /**
    * @Date 2021/3/22 14:25
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ScalaDataConvertDemo02 {
    def main(args: Array[String]): Unit = {
    val num1: Int = 10 * 3.5.toInt + 6 * 1.5.toInt
    println("num1 = " + num1) // 36
    var num2: Int = (10 * 3.5 + 6 * 1.5).toInt
    println("num2 = " + num2) // 44


    var char1: Char = 1
    var num3 = 1
    // val char2: Char = num3,报错:
    // 因为Char类型可以保存 Int的常量值,但不能保存Int的变量值,需要强转
    }
    }

    ~~~~

    #### 值类型转换

    ~~~~scala
    // 判断是否能够通过编译,并说明原因
    var s : Short = 5 // ok
    s = s-2 // error Int -> Short
    var b : Byte = 3 // ok
    b = b + 4 // error Int ->Byte
    b = (b+4).toByte // ok ,使用强制转换
    var c : Char = 'a' //ok
    var i : Int = 5 //ok
    var d : Float = .314F //ok
    var result : Double = c+i+d //ok Float->Double
    var b : Byte = 5 // ok
    var s : Short = 3 //ok
    var t : Short = s + b // error Int->Short
    var t2 = s + b // ok, 使用类型推导
    ~~~~

    #### 值类型和String类型的转换

    在程序开发中,我们经常需要将基本数据类型转成String 类型。或者将String类型转成基本数据类型。

    ##### 基本类型转String类型

    > `将基本类型的值+"" 即可`

    ##### String类型转基本数据类型

    > `通过基本类型的String的toXxx方法即可`

    ##### 注意事项

    > 1. 在将String 类型转成 基本数据类型时,要确保String类型能够转成有效的数据,比如 我们可以把 "123" , 转成一个整数,但是不能把 "hello" 转成一个整数。
    >
    > 2. 思考就是要把 "12.5" 转成 Int ?

    ~~~~scala
    /**
    * @Date 2021/3/22 14:36
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ScalaStringToOther {
    def main(args: Array[String]): Unit = {
    var str = "12.5"

    //在scala中,不是将小数点后的数据进行截取,而是会抛出异常
    //println(str.toInt) 报错

    println(str.toDouble)//12.5

    // 思考就是要把"12.5"转成Int
    println(str.toDouble.toInt)
    }
    }
    ~~~~

    ### 4. 标识符的命名规范

    > 1. ==Scala 对各种变量、方法、函数等命名时使用的字符序列称为标识符。==
    > 2. 凡是自己可以起名字的地方都叫标识符。

    #### 标识符的命名规则(记住)

    > 1. ==Scala中的标识符声明,基本和Java是一致的==,但是细节上会有所变化。
    > 2. 首字符为字母,后续字符任意字母和数字,美元符号,可后接下划线_
    > 3. 数字不可以开头。
    > 4. `首字符为操作符(比如+ - * / ),后续字符也需跟操作符 ,至少一个`
    > 5. 操作符(比如+-*/)不能在标识符中间和最后。
    > 6. 用反引号``....``包括的任意字符串,即使是关键字(39个)也可以 [true]

    ~~~~scala
    /**
    * @Date 2021/3/22 14:51
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ScalaIdenDemo01 {
    def main(args: Array[String]): Unit = {
    val ++ = "Hello Scala"
    println(++)

    val -+*/ = 90
    println(-+*/)

    //其实编译器是进行以下处理的:
    // ++ ==> $plus$plus

    //val +a = "abc" 报错

    var `boolean` = "true"
    println(`boolean`)
    val Int = 90.44

    println(Int) //Double类型

    // 不能使用 _ 做标识符
    var _ = "jack"
    //println(_)
    }
    }
    ~~~~

    #### 标识符举例说明

    ~~~scala
    hello // ok
    hello12 // ok
    1hello // error
    h-b // error
    x h // error
    h_4 // ok
    _ab // ok
    Int // ok, 在scala中,Int 不是关键字,而是预定义标识符,可以用,但是不推荐
    Float // ok
    _ // 不可以,因为在scala中,_ 有很多其他的作用,因此不能使用
    Abc // ok
    +*- // ok
    +a // error
    ~~~

    #### 标识符命名注意事项

    ~~~~scala
    //包名:尽量采取有意义的包名,简短,有意义。
    //变量名、函数名 、方法名 采用驼峰法。
    ~~~~

    #### Scala有39个关键字

    ~~~scala
    package, import, class, object, trait, extends, with, type, forSome
    private, protected, abstract, sealed, final, implicit, lazy, override
    try, catch, finally, throw
    if, else, match, case, do, while, for, return, yield
    def, val, var
    this, super
    new
    true, false, null
    ~~~

    ## ☆

  • 相关阅读:
    3.10_eclipse的使用和Object类型
    团队项目推荐:礼物推荐 —— by Xizhou
    团队项目推荐:不一样的旅游——by Lijun
    团队项目推荐:自动化卡通人脸生成——by Feng Nie
    团队项目推荐:手机社交照片管理软件——by Zhaofan
    Team Project Proposal:App:等车时间预测(重写) -- by DengPan
    对MSRA-USTC 2011的 meng-meng(萌萌) 的team project的学习和评价
    Team Project Proposal: All-in-one多信息源整合的移动应用[Revised in 8th Oct]——by Yuchan
    Team Project Proposal:App:等车时间预测 -- by DengPan
    Team Project Proposal:手机音频美化APP——by Kun Qian
  • 原文地址:https://www.cnblogs.com/huaobin/p/15756202.html
Copyright © 2011-2022 走看看