- 一, 简单入门
- 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 循环中断
-
Java的扩展和延伸
- Scala基于JVM, 和Java完全兼容, 同样具有跨平台,可以执行好,方便的垃圾回收等特性;
- Scala是一种纯粹的面向对象语言;
- Scala是一门函数式编程语言;
-
Scala更适合大数据的处理
- Scala对集合类型数据处理有非常好的支持
- Sparkd的底层用Scla编写
- 安装和配置环境变量: 参考本文
- 在IDEA中配置Scala插件: 参考本文
具体编写过程
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 的变量和常量
常量: 在程序执行的过程中, 值不会改变的变量
- Java中的变量和常量语法
- 变量类型 变量名 = 值, int a = 10;
- final 常量类型 常量名 = 值, final int b = 20;
- Scala中的变量和常量
注意:
- 声明变量时, 类型可以忽略, 编译器自动推导, 即类型推导;
- 类型确定后, 就不能修改, 说明Scala是强数据类型语言;
- 变量声明时, 必须要有初始值;
- 在声明/定义一个变量时, 可以使用var/val修饰, var修饰的变量可改变, val修饰的变量不可改;
[案例一, 变量声明和赋值]
- 类型自动推导;
- 强类型语言;
- 声明变量时必须赋值;
- 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 在对象修改上的不同]
- var修饰的对象引用可以直接改变;
- val修饰的对象引用不可以改变, 但是对象的状态(引用的值)可以改变;
- Scala 对各种变量、方法、函数等命名时使用的字符序列称为标识符。即:凡是自己可以起名字的地方都叫标识符。
命名规则:
1. 字符,下划线,$开头, 后接字母,数字,下划线;
2. 以 *** 作符开头, 且只包含 *** 作符(+ - * / # ! 等 的任意组合)
3. 用反引号 ``包括的任意字符串, 即便是Scala关键字也可以这样作为标识符;
第一点跟Java命名规则是一致的, 下面2,3条简直是绝了, 闻所未闻的;
[案例: 分辨标识符正确与否]
- h-b不对, 是_ 这种叫下划线, 没有-这一说
- x h, 标识符中不能存在空格
- Int, 保留字不行, 加上``反引号倒是可以
- 有 *** 作符的话, 就只能全是 *** 作符, 所以 +*-/#!1 不对
- if 不对, 保留字
- 基本语法
- 字符串, 通过+号连接;
- printf用法: 格式化字符串, 通过%传值;
- 字符串模板(插值字符串): 通过$获取变量值;
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) } }
2.4 Scala键盘输入, 文件读写初探拓展: Java中printf的用法
- 语法:
- 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 数据类型
- Java中的数据类型
- Java 数据类型详解, 参见此文: Java基础必会语法复习
2.5.1 Unit, Null, Nothing 类型
- Scala中的数据类型
|数据类型|描述|
|Unit| 表示无值, 和其他语言中的void等同, 用作不返回任何结果的方法的结果类型; Unit只有一个实例值, 写成()|
|Null| null, Null类型只有一个实例值null|
|Nothing|Nothing类型处于Scala的类层级最底端, 他是任何其他类型的子类型; 当一个函数, 我们确定没有正常的返回值, 可以用Nothing来指定返回类型, 这样有一个好处, 就是我们可以把返回的值(异常)赋给其他的函数或者变量(兼容性)|
[案例]
- Unit 类型
- 用来标识过程, 也就是没有明确返回值的函数
为什么把Unit类型的方法打印输出是一对括号()? Unit源码分析:
- Null类
- 只有一个实例值,即null, 表示空引用
- Null类似于Java中的null引用.
- Null类可以赋值给任意引用类型(AnyRef), 但是不能赋值给值类型(AnyVal)
- Nothing
- 没有任何实例对象;
- 作为没有正常返回值的方法的返回类型, Nothing可以告诉你, 这个方法不会正常返回;
- 而且由于Nothing是其他任意类型的子类, 他还能跟要求返回值的方法兼容;
- 扩展阅读: 理解Scala语言中Null/Nothing/Nil/None/Unit的区别
2.5.2.1 隐式转换Scala和Java 的数据类型转换是一致的,
- 数据从精度小的(数据类型表示范围小的)-->精度大的(数据类型表示范围大的), 会进行自动类型转换(隐式转换);
- 相反, 由大 --> 小, 必须进行手动强制类型转换 xx.toInt
- Java, Scala 的自动转换
2.5.2.2 强制类型转换 2.5.2.3 数值类型和 String类型之间的转换
- 自动提升原则: 有多重类型的数据混合运算时, 系统首先将所有数据转换成精度大的那种数据类型, 然后再进行计算;
- 把精度大的数值类型复制给精度较小的数值类型时, 就会报错, 反之就会进行自动类型转换;
- (Byte, Short)这俩各自和 char之间不会相互自动转换
- 但是,Byte, Short, Char他们三者可以组合就散, 在计算时首先会自动转为Int类型;
实际的编程中, 经常能用到数值和字符串之间的互转, 来我们回忆下在Java中是怎样实现数值和字符串互转的:
- 数值==>字符串, 会用到String类的包装方法, String.valueOf(数值变量)
- 字符串==> 数值, 根据数值对应的数据类型的不同, 数值的包装类.parse数值(数值变量), 比如, Integer.parseInt(intval)
那么, Scala是怎么进行转换的呢?
- 数值==>字符串, 直接使用 +""拼接,
- 字符串==> 数值, 根据数值的数据类型不同, (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中,
- 对于基本数据类型, ==是用来比较值的大小是否相等, 而对于引用数据类型, ==用来比较引用的地址值是否相等;
- 另外, equals()作为Object类的方法, 通常是用来比较两个引用数据的地址是否相等, 然而在String, Integer, Date类中对equals()进行了重写, 用来比较两个值是否相等;
在Scala中,
- 由于Scala中的数据类型全是引用数据类型, 也就相对没有Java那么令人凌乱了, ==和 equals() 都是用来比较两个变量的值是否相等
- 而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, 除不尽的话就直接保留整数, 舍弃小数点;
四, 流程控制 4.1 分支控制 if-elseScala 运算符的本质(方法)
分支控制让程序有选择的执行, 分支控制有三种: 单分支, 双分析, 多分支
- Scala中的分支控制逻辑基本与Java一致, 但是最大的不同在于, Scala中的 if else{} 表达式是有返回值的,
- 具体返回值内容取决于满足条件的分支代码体中的最后一行内容,
- 如果是一个字符串"", 那么就返回这一行字符串, 如果是一个变量, 或一个输出语句, 就返回()
- 注意: scala中if else表达式是有返回值的,且默认返回类型是Any类型,在根据实际返回的数值进行推断,如果if或者else返回的类型不一样,就返回Any类型(所有类型的公共超类型)。
- Java中的三元运算符可以用if else 实现
- Java的三元运算符: 判断条件 ? 条件为true的执行内容 : 条件为false的执行内容
- Scala的三元运算符: if(判断条件) 条件为true的执行内容 else 条件为false的执行内容
4.3 Switch 分支 (无, 使用模式匹配处理, 后面补充) 4.4 For 循环控制(就上面的if-else 套娃呗, 没啥可讲的)
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)
- 循环守卫, 即循环保护式(或条件判断, 守卫)
- 保护式为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.6 循环中断Scala中的While, do…While循环和Java中的用法完全一致
- 与 for 语句不同,while 语句没有返回值,即整个 while 语句的结果是 Unit 类型()
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") } } } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)