一, Scala基础语法全总结

一, Scala基础语法全总结,第1张

一, Scala基础语法全总结

文章目录
  • 一, 简单入门
    • 1.1 为什么要学习Scala?
    • 1.2 Scala 与 Java, JVM的关系
    • 1.3 Scala语言的特点
    • 1.4 Scala 安装和IDE的配置
    • 1.5 HelloWorld 案例
    • 1.6 对反编译Scala字节码文件的解读
    • 1.7 Scala 中的 Object和Class
  • 二, 变量和数据类型
    • 2.1 注释
    • 2.2 Scala 的变量和常量
    • 2.2 标识符
    • 2.3 字符串
    • 2.4 Scala键盘输入, 文件读写初探
    • 2.5 Scala 数据类型
      • 2.5.1 Unit, Null, Nothing 类型
      • 2.5.2 Scala 数据类型转换
        • 2.5.2.1 隐式转换
        • 2.5.2.2 强制类型转换
        • 2.5.2.3 数值类型和 String类型之间的转换
  • 三, 运算符
    • 3.1 算术运算符
    • 3.2 关系运算符
    • 3.3 赋值运算符
    • 3.4 位运算符
  • 四, 流程控制
    • 4.1 分支控制 if-else
    • 4.2 嵌套分支
    • 4.3 Switch 分支 (无, 使用模式匹配处理, 后面补充)
    • 4.4 For 循环控制
      • 4.4.1 范围数据循环(to)--> 左闭右闭
      • 4.4.2 范围数据循环(Until)--> 左闭右开
      • 4.4.3 循环守卫( if xx)
      • 4.4.4 循环步长(by)
      • 4.4.4 嵌套循环(多重循环)
      • 4.4.6 引入变量
      • 4.4.7 循环返回值
    • 4.5 While 和 do..While 循环控制
    • 4.6 循环中断

一, 简单入门 1.1 为什么要学习Scala?
  1. Java的扩展和延伸

    • Scala基于JVM, 和Java完全兼容, 同样具有跨平台,可以执行好,方便的垃圾回收等特性;
    • Scala是一种纯粹的面向对象语言;
    • Scala是一门函数式编程语言;
  2. Scala更适合大数据的处理

    • Scala对集合类型数据处理有非常好的支持
    • Sparkd的底层用Scla编写
1.2 Scala 与 Java, JVM的关系

1.3 Scala语言的特点

1.4 Scala 安装和IDE的配置
  1. 安装和配置环境变量: 参考本文
  2. 在IDEA中配置Scala插件: 参考本文
1.5 HelloWorld 案例

具体编写过程

object HelloWorld{
    //定义方法 main ==        def 方法名(参数名: 参数类型):返回值 ={}
    def mian(args: Array[String]): unit={
        println("Hello World!!")
    }
}

1.6 对反编译Scala字节码文件的解读

待补充

1.7 Scala 中的 Object和Class

待补充

二, 变量和数据类型 2.1 注释

Scala的注释使用和Java 完全相同

//  	1.单行注释

 	2. 多行注释



2.2 Scala 的变量和常量

常量: 在程序执行的过程中, 值不会改变的变量

  1. Java中的变量和常量语法
  • 变量类型 变量名 = 值, int a = 10;
  • final 常量类型 常量名 = 值, final int b = 20;
  1. Scala中的变量和常量
变量写法实例var 变量名 [: 变量类型] = 初始值var i:Int = 10 常量写法实例val 常量名 [:常量类型] = 初始值var j:Int = 20

注意:

  1. 声明变量时, 类型可以忽略, 编译器自动推导, 即类型推导;
  2. 类型确定后, 就不能修改, 说明Scala是强数据类型语言;
  3. 变量声明时, 必须要有初始值;
  4. 在声明/定义一个变量时, 可以使用var/val修饰, var修饰的变量可改变, val修饰的变量不可改;

[案例一, 变量声明和赋值]

  1. 类型自动推导;
  2. 强类型语言;
  3. 声明变量时必须赋值;
  4. val的值不可变, var可变;
object TestValAndVar {

  //1. 类型推导; 声明变量时, 类型可以忽略, 编译器会自动推导;
  var a1 = 10;
  var a2:Int = 10;
  var b3 = "areusb?";
  val c5 = false;

  //2. 强类型语言; 变量/常量的数据类型确定后, 就不能再修改
  var e3:Int = 250;
  e3 = "feswgf"; //编译器不会对此句报错, 执行时才会报错 type mismatch, 看下图

  //3. 声明变量时必须有初始值;
  var e4:Int; // 抱错如下图所示

  //4. var可变, va不可变
  var f4 = 6;
  f4 = 9;

  val f5 = 100;
  f5 = 200; //编译器当场报错;
  def main(args : Array[String]): Unit = {
     println(a1 + b3  + e4)

  }
}

[案例二, var, val 在对象修改上的不同]

  1. var修饰的对象引用可以直接改变;
  2. val修饰的对象引用不可以改变, 但是对象的状态(引用的值)可以改变;

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

命名规则:
1. 字符,下划线,$开头, 后接字母,数字,下划线;
2. 以 *** 作符开头, 且只包含 *** 作符(+ - * / # ! 等 的任意组合)
3. 用反引号 ``包括的任意字符串, 即便是Scala关键字也可以这样作为标识符;

第一点跟Java命名规则是一致的, 下面2,3条简直是绝了, 闻所未闻的;

[案例: 分辨标识符正确与否]

  • h-b不对, 是_ 这种叫下划线, 没有-这一说
  • x h, 标识符中不能存在空格
  • Int, 保留字不行, 加上``反引号倒是可以
  • 有 *** 作符的话, 就只能全是 *** 作符, 所以 +*-/#!1 不对
  • if 不对, 保留字
2.3 字符串
  1. 基本语法
  1. 字符串, 通过+号连接;
  2. printf用法: 格式化字符串, 通过%传值;
  3. 字符串模板(插值字符串): 通过$获取变量值;
object TestString {
  def main(args: Array[String]): Unit = {
    //1. + 字符串拼接,  另外, *是多次拼接字符串
    var str1:String = "Hello !"
    var str2:String = "Are u sb?"

    println("'+'拼接字符串, "+str1 + str2)

    println(str1*3) //Hello !Hello !Hello !

    //2. printf, 格式化字符串.
    // %d  整数, %s 字符串 , %f 输出浮点数
    var name = "liming"
    var age = 18
    var grade = 88.26

    printf("this is %s, and his age is %d , he got %2.3f in math exam;", name,age,grade)
    println()

    //3. 插值字符串(模板字符串),
    // 3.1 插值字符串的写法:  println(s"... ${变量名} ")
    //3.2 如何填入变量值呢?  ${变量名}, 插值就体现在这里

    //1. 典型的插值字符串,  println(s"待输入的字符串,  插入变量写为 ${变量名}")
    println(s"${name} is my friend, his math got ${grade}, which is so so but better than me")

    //2. 格式化的插值字符串, println(f"  ${变量名}%d"),
    // %%d  整数, %s 字符串 , %f 输出浮点数等等
    println(f"this is a 格式化字符串, 比如: ${grade}%2.6f")

    //3. 按照我们给定的字符串格式打印输出字符串, println(raw" ");
    println(raw"我用了个    空格, %d本来是格式化字符串(输出整数), 使用了raw 原样输出了, ${name}, 但是插值还是能用的")

    //4. 三引号, 保持多行字符串的原始格式输出
    var ss = s"""
       |我这个可是
       |多行字符串输出噢, 甭管你是任何的
       |格式化字符串, %d, %f, %u, 不管你, 但是
       |插值还是可以用的噢
       |""".stripMargin
    println(ss)
  }
}

拓展: Java中printf的用法

2.4 Scala键盘输入, 文件读写初探
  • 语法:
    • StdIn.readLine() 读取字符串
    • StdIn.readShort() 读取Short类型的值
    • StdIn.readDouble() 读取Double类型的值

[案例: 键盘输入, 文件读写]

import java.io.{File, FileWriter}
import scala.io.{Source, StdIn}

object TestInAndOut {
  def main(args: Array[String]): Unit = {
    //读取字符串
    println("请输入姓名: ")
    val name: String = StdIn.readLine()

    println("请输入年龄: ")
    val age: Int = StdIn.readInt()

    println(s"You are ${age}, your name is ${name}")

    //读文件, Source.fromFile(path).foreach(print)
    Source.fromFile("D:\Code\IdeaWorkSpace\scala_demo\src\main\resources\read.txt").foreach(print)

    //写文件, Scala写文件借助的还是Java 的IO流
    val writer = new FileWriter(new File("D:\Code\IdeaWorkSpace\scala_demo\src\main\resources\writeRes.txt"))
    
    val outStr: String = ""Scala读文件, Source.fromFile(path).foreach(print)"";
    
    writer.write(outStr)
    writer.close()
  }
}
2.5 Scala 数据类型
  1. Java中的数据类型

  • Java 数据类型详解, 参见此文: Java基础必会语法复习

  1. Scala中的数据类型

2.5.1 Unit, Null, Nothing 类型

|数据类型|描述|
|Unit| 表示无值, 和其他语言中的void等同, 用作不返回任何结果的方法的结果类型; Unit只有一个实例值, 写成()|
|Null| null, Null类型只有一个实例值null|
|Nothing|Nothing类型处于Scala的类层级最底端, 他是任何其他类型的子类型; 当一个函数, 我们确定没有正常的返回值, 可以用Nothing来指定返回类型, 这样有一个好处, 就是我们可以把返回的值(异常)赋给其他的函数或者变量(兼容性)|

[案例]

  1. Unit 类型
  • 用来标识过程, 也就是没有明确返回值的函数

为什么把Unit类型的方法打印输出是一对括号()? Unit源码分析:

  1. Null类
  • 只有一个实例值,即null, 表示空引用
  • Null类似于Java中的null引用.
  • Null类可以赋值给任意引用类型(AnyRef), 但是不能赋值给值类型(AnyVal)

  1. Nothing
  • 没有任何实例对象;
  • 作为没有正常返回值的方法的返回类型, Nothing可以告诉你, 这个方法不会正常返回;
  • 而且由于Nothing是其他任意类型的子类, 他还能跟要求返回值的方法兼容;
  • 扩展阅读: 理解Scala语言中Null/Nothing/Nil/None/Unit的区别
2.5.2 Scala 数据类型转换

Scala和Java 的数据类型转换是一致的,

  1. 数据从精度小的(数据类型表示范围小的)-->精度大的(数据类型表示范围大的), 会进行自动类型转换(隐式转换);
  2. 相反, 由大 --> 小, 必须进行手动强制类型转换 xx.toInt
2.5.2.1 隐式转换
  • Java, Scala 的自动转换

  1. 自动提升原则: 有多重类型的数据混合运算时, 系统首先将所有数据转换成精度大的那种数据类型, 然后再进行计算;
  2. 把精度大的数值类型复制给精度较小的数值类型时, 就会报错, 反之就会进行自动类型转换;
  3. (Byte, Short)这俩各自和 char之间不会相互自动转换
  4. 但是,Byte, Short, Char他们三者可以组合就散, 在计算时首先会自动转为Int类型;
2.5.2.2 强制类型转换

2.5.2.3 数值类型和 String类型之间的转换

实际的编程中, 经常能用到数值和字符串之间的互转, 来我们回忆下在Java中是怎样实现数值和字符串互转的:

  1. 数值==>字符串, 会用到String类的包装方法, String.valueOf(数值变量)
  2. 字符串==> 数值, 根据数值对应的数据类型的不同, 数值的包装类.parse数值(数值变量), 比如, Integer.parseInt(intval)

那么, Scala是怎么进行转换的呢?

  1. 数值==>字符串, 直接使用 +""拼接,
  2. 字符串==> 数值, 根据数值的数据类型不同, (s1.toInt, s1.toByte, s1.toLong, s1.toShort)

var n5:Int = “12.6”.toInt 会出现 NumberFormatException 异常。

来看一道面试题:(待补充)

三, 运算符

Scala 运算符的使用和 Java 运算符的使用基本相同,只有个别细节上不同。

3.1 算术运算符

3.2 关系运算符

Java和Scala中 == 和 equals()的异同点:

在Java中,

  1. 对于基本数据类型, ==是用来比较值的大小是否相等, 而对于引用数据类型, ==用来比较引用的地址值是否相等;
  2. 另外, equals()作为Object类的方法, 通常是用来比较两个引用数据的地址是否相等, 然而在String, Integer, Date类中对equals()进行了重写, 用来比较两个值是否相等;

在Scala中,

  1. 由于Scala中的数据类型全是引用数据类型, 也就相对没有Java那么令人凌乱了, ==和 equals() 都是用来比较两个变量的值是否相等
  2. 而Scala用什么比较引用地址值? Scala使用单独的一个 eq() 来比较两个对象的引用地址
object HelloWorld {
    def main (args: Array[String]): Unit= {
      //1. 比较值是否相等, ==或equals()
      val num1: Int = 2
      val num2: Int = 2

      val str1: String = "liming"
      val str2: String = "liming"

      println("Scala使用 ==或quals() 来比较两个变量的值是否相等: ")
      println("num1 和 num2 相等吗? " + (num1 == num2))
      println("num1 和 num2 相等吗? " + (num1.equals(num2)))

      println("str1 和 str2 相等吗? " + (str1 == str2))
      println("str1 和 str2 相等吗? " + (str1.equals(str2)))
      
      //2. 比较引用是否相等
      println("=========================================")

      println("Scala使用 eq()  比较两个变量引用的地址值是否相等")
      println("num1 和 num2 的地址相等吗? " + (str1.eq(str2)))
    }
}

3.3 赋值运算符

3.4 位运算符

  • 位运算符是一种比较底层的计算方式,
  • 按位左移, << , 移动n位, 就是把原数x2n
  • 按位右移, >> , 移动m位, 就是把原数/2m, 除不尽的话就直接保留整数, 舍弃小数点;

Scala 运算符的本质(方法)

四, 流程控制 4.1 分支控制 if-else

分支控制让程序有选择的执行, 分支控制有三种: 单分支, 双分析, 多分支

  1. Scala中的分支控制逻辑基本与Java一致, 但是最大的不同在于, Scala中的 if else{} 表达式是有返回值的,
  • 具体返回值内容取决于满足条件的分支代码体中的最后一行内容,
  • 如果是一个字符串"", 那么就返回这一行字符串, 如果是一个变量, 或一个输出语句, 就返回()
  1. 注意: scala中if else表达式是有返回值的,且默认返回类型是Any类型,在根据实际返回的数值进行推断,如果if或者else返回的类型不一样,就返回Any类型(所有类型的公共超类型)。
  1. Java中的三元运算符可以用if else 实现
  • Java的三元运算符: 判断条件 ? 条件为true的执行内容 : 条件为false的执行内容
  • Scala的三元运算符: if(判断条件) 条件为true的执行内容 else 条件为false的执行内容
4.2 嵌套分支

(就上面的if-else 套娃呗, 没啥可讲的)

4.3 Switch 分支 (无, 使用模式匹配处理, 后面补充) 4.4 For 循环控制

Scala也为for循环这一常见的控制结构提供了非常多的特性, 这些for循环的特性被称为for推导式或for表达式;

4.4.1 范围数据循环(to)–> 左闭右闭

[基本用法]

// 把[0,10]的每一个整数, 循环赋值给i
for(i <- 0 to 10){
  print(i + " ")
}

// 0 to 10 等同于 0.to(10),  to就是方法噢
  • i表示循环变量, to表示的是循环从0到10(包括10)

如何倒序遍历? 加个reverse即可;

for(i <- 0 to 10){
  print(i + " ")
}
4.4.2 范围数据循环(Until)–> 左闭右开

[基本用法]

// 把[0,10)的每一个整数, 循环赋值给i
for(i <- 0 until 10){
  print(i + " ")
}

//或者使用下面这种方式, Range(a,b)
for(i <- Range(0,10)){
  print(i + " ")
}
  • i表示循环变量, until表示的是循环从0到10(不包括10)
4.4.3 循环守卫( if xx)
  • 循环守卫, 即循环保护式(或条件判断, 守卫)
  • 保护式为true则进入循环体内部, 为false则跳过本次循环, 类似于continue

[基本用法]

for(i <- 1 to 3 if i != 2){
  print(i + " ")
}
  • 上面的写法等同于:
for(i <- 1 to 3){
   if (i != 2){
      print(i + " ")
   }
}
4.4.4 循环步长(by)

[基本用法]

// 步长为2的循环遍历
// 注意噢, 步长不能为 0, 可以为正, 负, 浮点数(可能会精度出错)
for (i <- 0 to 10 by 2) {
println("i=" + i)
}
4.4.4 嵌套循环(多重循环)

[案例一, 九九乘法表]

object NineNideMultiple {
  def main(args: Array[String]): Unit = {
    //九九乘法表
    //外层循环遍历1 to 9, 内层循环 i * (1 - > 9)

    
    for(i <- 1 to 9){
      for(j <- 1 to i){
        print(s"${i} x ${j} = ${i * j} t")
      }
      println()
    }
    println("========================================")
    for(i <- 1 to 9; j <- 1 to i){
      print(s"${i} x ${j} = ${i * j} t")
        if(j == i) println()
    }
    
  }
}

4.4.6 引入变量


4.4.7 循环返回值

4.5 While 和 do…While 循环控制

Scala中的While, do…While循环和Java中的用法完全一致

  • 与 for 语句不同,while 语句没有返回值,即整个 while 语句的结果是 Unit 类型()
4.6 循环中断

Scala内置控制结构去掉了break和continue, 是为了更好的适应函数式编程, 推荐使用函数式的风格解决break和continue的功能, 而不是一个关键字.
Scala 中使用breakable 控制结构来实现break和continue功能

需求 1:采用异常的方式退出循环

def main(args: Array[String]): Unit = {
  try {
    for (elem <- 1 to 10) {
      println(elem)
      if (elem == 5) throw new RuntimeException
    }
  }catch {
    //模式匹配
    case e: Exception =>   //啥都不做. 退出循环
    }
  println("正常结束循环")

需求 2:采用 Scala 自带的函数,退出循环

import scala.util.control.Breaks
def main(args: Array[String]): Unit = {
    Breaks.breakable(
    for (elem <- 1 to 10) {
println(elem)
if (elem == 5) Breaks.break()
}
)
println("正常结束循环")
}

需求 3:对 break 进行省略

import scala.util.control.Breaks._
object TestBreak {
def main(args: Array[String]): Unit = {
breakable {
for (elem <- 1 to 10) {
println(elem)
if (elem == 5) break
}
}
println("正常结束循环")
}
}

需求 4:循环遍历 10 以内的所有数据,奇数打印,偶数跳过(continue)

object TestBreak {
def main(args: Array[String]): Unit = {
for (elem <- 1 to 10) {
if (elem % 2 == 1) {
println(elem)
} else {
println("continue")
}
}
}
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5685230.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存