1 入门学习笔记
笔记适配有 Java 基础的大数据专业,严格匹配 Scala 入门课程体系,贴合 Spark/Flink 大数据开发的后续学习需求,全程Java 语法对比 + 可运行代码案例 + 随堂练习 + 避坑指南,零基础也能快速上手,学完可直接衔接 Scala 核心语法与大数据开发。
- 前置知识:Java 基础语法、JVM 基础原理
- 开发环境:JDK1.8+、Scala2.12.x(Spark/Flink 主流兼容版本)、IDEA + Scala 插件
第一章 Scala 入门概述
1.1 为什么大数据专业必须学 Scala?
对于大数据开发而言,Scala 是绕不开的核心语言,核心原因有 3 点:
大数据主流框架的原生语言
Spark、Flink 两大主流大数据计算框架均由 Scala 开发,原生提供 Scala API,且 Scala API 比 Java API 更简洁、更贴合框架的设计思想,大数据开发岗位中 Scala 是核心技能要求。
行业认可度与薪资优势
Stack Overflow 全球编程语言薪资排行中,Scala 长期稳居前列,国内大数据开发岗位中,Scala 开发者薪资普遍比同级别 Java 开发者高 10%-30%,薪资集中在 20-50K 区间。
技术大牛的高度认可
- Java 之父 James Gosling:除了 Java,JVM 上最推荐的语言就是 Scala。
- Groovy 语言创始人 James Strachan:如果早看到 Scala,根本不会去发明 Groovy,Scala 完全可以替代 Java。
1.2 Scala 是什么
Scala 是**Scalable Language(可扩展语言)*的缩写,由瑞士洛桑联邦理工学院(EPFL)的 Martin Odersky(Java javac 编译器的核心开发者)于 2001 年开始设计,2003 年底发布 Java 平台正式版,是一门*融合了面向对象编程与函数式编程的多范式编程语言。
- 运行基础:Scala 代码会被编译成 Java 字节码,运行在 JVM 上,与 Java 完全无缝兼容,可以直接调用 Java 的所有类库。
- 核心设计目标:用简洁的语法实现高扩展性,既保留了面向对象的工程化能力,又具备函数式编程的简洁性,非常适合大数据的并行计算场景。
1.3 Scala 核心特性(与 Java 核心对比)
针对有 Java 基础的学习者,重点掌握 Scala 与 Java 的核心差异,快速建立认知:
表格
| 特性 | Scala | Java | 大数据场景价值 |
|---|---|---|---|
| 编程范式 | 面向对象 + 函数式编程双范式,纯面向对象(连基本类型、运算符都是对象) | 主要面向对象,仅支持 Lambda 表达式的函数式简化 | 函数式编程天然适合大数据的并行计算、集合处理,代码量比 Java 少 70% 以上 |
| 静态类型 | 自适应静态类型,支持自动类型推断,绝大多数场景无需手动声明类型 | 强制静态类型,除了 var 局部变量,必须手动声明类型 | 代码更简洁,同时保留静态类型的安全性,避免大数据任务的运行时类型错误 |
| 代码简洁性 | 极简语法,无冗余代码,一行代码可实现 Java 数十行的逻辑 | 语法繁琐,大量模板化代码 | 大数据开发中,数据处理逻辑更清晰,维护成本更低 |
| 并发模型 | 基于事件的 Actor 并发模型,更适合分布式场景 | 基于线程、锁的并发模型,开发难度高 | 适配大数据分布式计算的并发场景,开发更简单 |
| 与 JVM 兼容性 | 完全兼容 Java,可直接调用所有 Java 类库,也可被 Java 调用 | JVM 原生语言 | 可无缝对接大数据的 Java 生态(Hadoop、Hive 等) |
1.4 Scala 的核心应用场景
- 大数据计算(核心场景):Spark、Flink、Kafka Streams 等大数据框架的核心开发语言,是大数据开发的首选语言。
- Web 应用开发:Play、Lift 等 Web 框架,开发效率远高于 Java 的 SSM/SpringBoot。
- 客户端 / 桌面应用:可开发跨平台的客户端程序。
- 脚本语言:可像 Shell/Python 一样作为脚本语言,快速开发数据处理脚本。
第二章 Scala 环境搭建与程序运行
2.1 环境准备
Scala 运行在 JVM 之上,必须先安装 Java 环境,版本要求如下:
- JDK:1.8 及以上版本(大数据场景统一使用 JDK1.8,避免兼容性问题)
- Scala:2.12.x 版本(Spark3.x、Flink1.15 + 均主流兼容 2.12 版本,不建议使用 2.13/3.x 版本)
2.2 Windows 系统安装与环境配置
步骤 1:下载 Scala 安装包
官方下载地址:https://www.scala-lang.org/downloads
选择对应版本的 Windows 安装包:scala-2.12.10.msi(msi 安装包,一键安装)或scala-2.12.10.zip(免安装压缩包)。
步骤 2:安装 Scala
- msi 安装包:直接双击,一直点击「下一步」即可,默认安装路径
C:\Program Files (x86)\Scala。 - zip 压缩包:解压到无中文、无空格的路径,例如
D:\scala-2.12.10。
步骤 3:配置环境变量
- 新建系统变量
SCALA_HOME,值为 Scala 的安装路径,例如D:\scala-2.12.10。 - 编辑系统变量
Path,新增一条:%SCALA_HOME%\bin。 - 点击「确定」保存所有配置。
步骤 4:验证安装
打开 Windows 命令提示符(CMD),输入以下命令,输出版本号即安装成功:
# 查看Scala版本
scala -version
# 查看Scala编译器版本
scalac -version2.3 Scala 程序的编译与运行(与 Java 对比)
Scala 的编译运行原理与 Java 几乎完全一致,只是命令不同,有 Java 基础的同学可以快速理解:
表格
| 操作 | Java | Scala |
|---|---|---|
| 源文件后缀 | .java | .scala |
| 编译命令 | javac 文件名.java | scalac 文件名.scala |
| 编译产物 | .class字节码文件 | .class字节码文件 |
| 运行命令 | java 类名 | scala 类名 |
| 反编译命令 | javap 类名 | scalap 类名 |
核心原理
Scala 和 Java 一样,都是先将源文件编译成 JVM 可识别的.class字节码文件,再由 JVM 执行字节码,这也是 Scala 能与 Java 无缝兼容的核心原因。
2.4 HelloWorld 案例详解
Scala 的程序入口有两种写法,均必须定义在object(单例对象)中,这是与 Java 的核心差异(Java 的入口必须是类中的public static void main方法)。
案例 1:标准 main 方法入口(与 Java 最相似,新手首选)
- 新建文件
HelloWorld.scala,写入以下代码:
/**
* Scala HelloWorld 标准写法
* object:Scala的单例对象关键字,等同于Java的单例类
* 程序入口必须写在object中,不能写在class中
*/
object HelloWorld {
/**
* 程序入口main方法,与Java的main方法功能完全一致
* 语法:def 方法名(参数名:参数类型):返回值类型 = { 方法体 }
* args: Array[String]:字符串数组参数,对应Java的String[] args
* Unit:等同于Java的void,表示无返回值
*/
def main(args: Array[String]): Unit = {
// 控制台打印语句,等同于Java的System.out.println
println("Hello Scala! 大数据开发,我们来了!")
}
}- 编译与运行
# 1. 编译源文件,生成HelloWorld.class字节码文件
scalac HelloWorld.scala
# 2. 运行程序
scala HelloWorld- 运行结果
Hello Scala! 大数据开发,我们来了!案例 2:继承 App 特质的极简入口(开发常用)
Scala 提供了App特质,可省略 main 方法,直接写业务代码,是开发中更常用的极简写法:
/**
* 继承App特质,自动实现程序入口
* 代码直接写在单例对象的花括号中,会自动执行
*/
object HelloWorldSimple extends App {
println("Hello Scala! 极简入口写法")
}编译运行方式与案例 1 完全一致,运行结果:
Hello Scala! 极简入口写法与 Java 的核心差异说明
- Scala 的程序入口必须定义在
object单例对象中,不能定义在class类中;Java 的入口定义在类的静态方法中。 - Scala 没有
static静态关键字,用object单例对象实现静态成员的功能。 - Scala 的方法定义用
def关键字,参数声明格式为参数名:参数类型,与 Java 的参数类型 参数名相反。 - Scala 的
Unit等同于 Java 的void,表示方法无返回值。
2.5 REPL 交互式解释器使用
REPL(Read-Eval-Print Loop)是 Scala 的交互式解释器,类似于 Python 的交互式终端,可直接输入 Scala 代码并立即执行,非常适合新手学习、代码测试、快速验证逻辑。
启动 REPL
打开 CMD,直接输入scala命令,即可进入 REPL 终端,出现scala>提示符:
scala
Welcome to Scala 2.12.10 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_144).
Type in expressions for evaluation. Or try :help.
scala>REPL 核心常用命令
表格
| 命令 | 作用 |
|---|---|
:help | 查看所有 REPL 命令的帮助文档 |
:load 文件名.scala | 加载并执行外部的 Scala 源文件 |
:paste | 进入粘贴模式,可粘贴多行代码(如 if-else、类定义),按 Ctrl+D 结束粘贴并执行 |
:quit / :q | 退出 REPL 终端 |
:javap 类名 | 反编译查看类的字节码信息 |
REPL 基础使用案例
# 1. 直接计算表达式
scala> 1 + 2 * 3
res0: Int = 7
# 2. 定义变量
scala> val name = "大数据开发"
name: String = 大数据开发
# 3. 打印变量
scala> println(name)
大数据开发
# 4. 定义方法
scala> def add(a: Int, b: Int): Int = a + b
add: (a: Int, b: Int)Int
# 5. 调用方法
scala> add(10, 20)
res1: Int = 30注意:REPL 中自动生成的
res0、res1是系统自动定义的变量,可直接使用,例如println(res0)。
第三章 Scala 基础语法规范
3.1 标识符(命名规范)
标识符是编程时给变量、常量、类、方法、对象等起的名字,Scala 的标识符规则与 Java 大体一致,但有扩展,分为 4 大类:
1. 字母数字标识符(开发最常用,与 Java 一致)
- 以 ** 字母、下划线
_** 开头,后面可以跟字母、数字、下划线。 $符号在 Scala 中视为字母,但为编译器保留使用,开发中禁止以$开头命名标识符。- 不能以数字开头,不能是 Scala 的关键字。
- 规范:遵循驼峰命名法,类名 / 特质名首字母大写,变量 / 方法 / 对象名首字母小写。
2. 运算符标识符
由一个或多个运算符字符组成,运算符字符包括+、-、*、/、:、?、~、#等,例如+、:::、:->都是合法的标识符。
这是 Scala 的特殊语法,Scala 中所有运算符本质上都是方法调用,例如
1 + 2本质是1.+(2)。
3. 混合标识符
由字母数字标识符 + 下划线 + 运算符标识符组成,例如a_+、max_?都是合法的标识符。
4. 字面量标识符
用 ** 反引号** 包裹的任意字符串,都是合法的标识符。
- 核心作用:Scala 的关键字无法直接作为标识符,但用反引号包裹后就可以使用,例如
def、yield都是合法的。 - 大数据场景常用:调用 Java 类库时,若方法名是 Scala 的关键字,必须用反引号包裹,例如
thread.wait()。
随堂练习:标识符合法性判断
判断以下标识符是否合法,不合法的说明原因(答案在本节末尾):
age2.abc#@3.name_+4._value5.123abc6.yield7.def8.a b
3.2 Scala 关键字(保留字)
Scala 的关键字比 Java 更多,关键字不能作为标识符使用(除非用反引号包裹),下面按与 Java 的异同分类,方便有 Java 基础的同学记忆:
1. Scala 与 Java 共有的关键字
abstract, break, case, catch, class, def, do, else, extends, final, finally, for, if, import, new, null, package, private, protected, return, super, this, throw, try, true, false, while, with, yield2. Scala 独有,Java 没有的关键字
object, trait, val, var, sealed, implicit, lazy, match, type, forSome, override3. Java 有,Scala 没有的关键字
public, protected, private, static, void, enum, implements, interface, native, strictfp, synchronized, throws, transient, volatile, const, goto重点说明:Scala 没有
static、public关键字,Scala 中类和成员默认是 public 访问权限,用object单例对象实现静态功能。
3.3 注释
Scala 的注释语法与 Java完全一致,分为 3 种,注释不会被编译器编译,仅用于代码说明:
- 单行注释:
// 注释内容 - 多行注释:
/* 注释内容 */,多行注释不能嵌套。 - 文档注释:
/** 注释内容 */,用于生成 API 文档。
示例:
/**
* 文档注释:用户注册类
* 用于演示Scala注释语法
*/
class UserRegister {
// 单行注释:用户名,不可修改
val username: String = "zhangsan"
/*
多行注释
密码,可修改
*/
var password: String = "123456"
}3.4 分号自动推断(与 Java 核心差异)
分号;是 Scala 中表达式的分隔符,与 Java 不同的是,Scala 具备自动分号推断能力,绝大多数场景无需手动写分号。
分号推断核心规则
一行只有一个表达式时,行尾的分号可写可不写,编译器会自动推断添加。
一行有多个表达式时,表达式之间的分号必须手动填写,否则编译报错。
以下场景,编译器会推断表达式未结束,不会自动加分号:
- 行尾以不能结尾的字符结束,例如
.、+、-、*、/等运算符。 - 行尾的内容在括号
()或方括号[]内。
- 行尾以不能结尾的字符结束,例如
代码示例
object SemicolonDemo {
def main(args: Array[String]): Unit = {
// 1. 一行一个表达式,无需分号
val a = 10
val b = 20
// 2. 一行多个表达式,必须加分号
val c = 30; val d = 40; println(c + d)
// 3. 行尾是运算符,编译器推断表达式未结束,不会自动加分号
val sum = a +
b +
c
println("sum=" + sum) // 输出 sum=60
// 错误写法:行尾无运算符,换行后编译器会自动加分号,导致逻辑错误
// val sumError = a
// + b
// 等同于 val sumError = a; +b,sumError的值是10,而非30
}
}随堂练习:语句合法性判断
已知x=2,y=3,判断以下语句是否合法,合法的计算z的值(答案在本节末尾):
val z = x * yval z = x * y`val z = x
- y`
3.5 本节练习答案
标识符合法性判断答案
- 合法 2. 不合法,包含非法字符
#@3. 合法(混合标识符)4. 合法 5. 不合法,以数字开头 6. 不合法,是 Scala 关键字 7. 合法(字面量标识符)8. 不合法,包含空格。
语句合法性判断答案
- 合法,
z=6 - 合法,行尾是
*,编译器不自动加分号,z=6 - 不合法,行尾无运算符,编译器自动加分号,等同于
val z = x; *y,编译报错。
第四章 变量与常量(Scala 核心基础)
变量和常量是编程的基础,Scala 用val和var两个关键字区分常量和变量,这是与 Java 最核心的差异之一,也是大数据开发中最常用的语法。
4.1 val:不可变常量(重点)
核心定义
val用于声明不可变常量,常量在初始化赋值后,值不能被修改,等同于 Java 中用final修饰的常量。
- 语法:
val 常量名[:数据类型] = 初始值 - 核心特性:不可变性,赋值后无法修改,保证线程安全,是 Scala 函数式编程的核心,大数据并行计算场景中优先使用
val。
代码示例
object ValDemo {
def main(args: Array[String]): Unit = {
// 1. 标准声明:指定数据类型
val username: String = "zhangsan"
println(username)
// 2. 类型推断:省略数据类型,编译器自动推断
val age = 20 // 自动推断为Int类型
println(age)
// 3. 错误:val常量赋值后不能修改,编译报错
// username = "lisi"
// age = 30
}
}与 Java 的对比
// Scala val声明
val num: Int = 10
// 等同于Java的final常量
final int num = 10;4.2 var:可变变量
核心定义
var用于声明可变变量,变量初始化后,值可以被修改,等同于 Java 中的普通变量。
- 语法:
var 变量名[:数据类型] = 初始值 - 开发规范:Scala 中优先使用
val,仅当确实需要修改值时才使用var,减少可变状态,提升代码的安全性和并行性。
代码示例
object VarDemo {
def main(args: Array[String]): Unit = {
// 声明可变变量
var password: String = "123456"
println("原始密码:" + password)
// 修改变量值,合法
password = "654321"
println("修改后的密码:" + password)
// 类型推断
var score = 80
score = 90
println("分数:" + score)
}
}与 Java 的对比
// Scala var声明
var num: Int = 10
// 等同于Java的普通变量
int num = 10;4.3 变量的类型声明与类型推断
- 显式类型声明:在变量名后用
:类型指定数据类型,例如val name: String = "zhangsan"。 - 自动类型推断:Scala 具备自适应静态类型推断能力,若声明时直接赋值,可省略类型声明,编译器会自动根据赋值推断出变量的类型。
- 强制规则:变量必须在声明时初始化,不能先声明后赋值(与 Java 不同),否则编译报错。
错误示例
// 错误1:只声明不赋值,编译报错
val a: Int
var b: String
// 错误2:类型不匹配,编译报错
val num: Int = "hello"4.4 多变量声明
Scala 支持在一行中同时声明多个变量,简化代码:
object MultiVarDemo {
def main(args: Array[String]): Unit = {
// 1. 同时声明多个val常量,赋值相同
val a, b, c = 10
println(s"a=$a, b=$b, c=$c") // 输出 a=10, b=10, c=10
// 2. 同时声明多个var变量,分别赋值
var (x, y, z) = (10, 20, "scala")
println(s"x=$x, y=$y, z=$z") // 输出 x=10, y=20, z=scala
// 修改可变变量
x = 100
println(s"修改后的x=$x")
}
}4.5 lazy 懒加载变量
核心定义
用lazy关键字修饰的val常量,称为懒加载变量,该变量只有在第一次被使用时才会被初始化赋值,而非声明时初始化。
语法:
lazy val 常量名 = 初始值核心限制:只能修饰
val常量,不能修饰var变量。核心作用:
- 优化程序性能,延迟初始化耗时的操作,避免程序启动时的性能损耗。
- 解决继承中父类构造器使用子类变量导致的空指针问题(后续 trait 章节重点讲解)。
- 大数据场景中,用于延迟加载大数据资源、配置文件等。
代码示例
object LazyDemo {
// 普通val:声明时立即初始化
val normalVal: String = {
println("普通val变量初始化")
"普通变量"
}
// lazy懒加载val:只有第一次使用时才初始化
lazy val lazyVal: String = {
println("lazy懒加载变量初始化")
"懒加载变量"
}
def main(args: Array[String]): Unit = {
println("程序启动")
println("----------------")
println("访问普通val:" + normalVal)
println("----------------")
println("第一次访问lazyVal:" + lazyVal) // 第一次访问,触发初始化
println("----------------")
println("第二次访问lazyVal:" + lazyVal) // 第二次访问,不会重复初始化
}
}运行结果
普通val变量初始化
程序启动
----------------
访问普通val:普通变量
----------------
lazy懒加载变量初始化
第一次访问lazyVal:懒加载变量
----------------
第二次访问lazyVal:懒加载变量从运行结果可以清晰看到:普通 val 在程序启动时就完成了初始化,而 lazy 变量只有在第一次被访问时才会初始化,且仅初始化一次。
4.6 变量的内存模型(JVM 层面,结合 Java 基础)
Scala 的变量内存模型与 Java 完全一致,运行在 JVM 上,分为栈内存和堆内存:
- 栈内存:存储变量的引用(地址),以及基本类型的值,存取速度快,线程私有。
- 堆内存:存储对象的实际数据,所有线程共享,由垃圾回收器(GC)管理。
核心示例:val 与 var 的内存差异
class Person(val name: String, var age: Int)
object VarMemoryDemo {
def main(args: Array[String]): Unit = {
// val修饰的引用变量:引用地址不可变,但对象内部的var属性可变
val person = new Person("张三", 20)
// 合法:修改对象内部的var可变属性
person.age = 30
println(s"修改后的年龄:${person.age}")
// 非法:val修饰的引用变量,地址不可变,不能指向新的对象,编译报错
// person = new Person("李四", 25)
// var修饰的引用变量:引用地址可变,对象内部属性也可变
var person2 = new Person("李四", 25)
person2.age = 35 // 合法,修改属性
person2 = new Person("王五", 28) // 合法,修改引用地址
}
}关键结论
val修饰的变量,是变量的引用 / 值不可变,而非引用指向的对象内部不可变。- 若对象内部的属性是
var,即使对象引用是val,也可以修改内部属性,这是 Java 开发者极易混淆的点。
4.7 本章随堂练习
练习 1:语句合法性判断
判断以下语句是否合法,不合法的说明原因(答案在本节末尾):
val a = 10; a = 20var b: String = "hello"; b = "scala"lazy var c = 30val (x, y) = (10, 20)var d: Int; d = 100
练习 2:代码分析题
以下代码中,①、②、③哪个是合法语句?不合法的说明原因。
class Person {
val name = "Scala"
val sex = "男"
var age = 20
}
val person = new Person
person.name = "大数据" // ①
person.age = 30 // ②
person = new Person // ③4.8 本章练习答案
练习 1 答案
- 不合法,val 常量赋值后不能修改。
- 合法,var 变量可修改值,且类型匹配。
- 不合法,lazy 只能修饰 val,不能修饰 var。
- 合法,多变量声明。
- 不合法,变量必须声明时初始化,不能先声明后赋值。
练习 2 答案
- ① 不合法:name 是 val 常量,赋值后不能修改。
- ② 合法:age 是 var 变量,可修改值。
- ③ 不合法:person 是 val 常量,引用地址不可修改,不能指向新的对象。
第五章 课后作业全解析
对应课程配套作业,包含选择题、填空题、简答题、编程题全解析,可直接通过代码验证。
一、选择题
下列用来编译 Scala 文件的命令是(B)。
- A. scala B. scalac C. scalap D. javac
- 解析:scalac 是 Scala 的编译命令,scala 是运行命令,scalap 是反编译命令,javac 是 Java 的编译命令。
Java 文件编译之后产生的文件的拓展名是(C)。
- A. .java B. .scala C. .class D. .bat E. .exe
- 解析:Java 和 Scala 编译后的产物都是.class 字节码文件。
对于 Test.class 文件而言,能够正确运行出结果的命令是(D)。
- A. javac Test.class B. javac Test C. scala Test.class D. scala Test
- 解析:运行 Scala 编译后的 class 文件,用
scala 类名,无需加.class 后缀,与 Java 的java 类名一致。
Scala 程序能够跨平台的基础是(C)。
- A. JDK B. JRE C. JVM D. SDK E. J2SE
- 解析:Scala 和 Java 一样,依靠 JVM 实现跨平台,一次编译,到处运行。
下列各项中是 Scala 关键字的是(D)。
- A. break B. static C. public D. val E. yeild
- 解析:val 是 Scala 声明常量的关键字;break、static、public 都不是 Scala 的关键字;yeild 是拼写错误,正确的关键字是 yield。
下列各项中可以用作标识符的是(E)。
- A. def B. Int C. lazy D. 123abc E. sum
- 解析:sum 是合法的字母数字标识符;def、lazy 是关键字;Int 是类名,不建议作为标识符;123abc 以数字开头,不合法。
下列关于注释的说法正确的是(C)。
- A. Java 中注释一共只有两种格式:单行注释、多行注释。(错误,还有文档注释)
- B. 单行注释之间可以嵌套。(正确,但不是最佳答案)
- C. 多行注释之间不能嵌套。(正确,核心特性)
- D. 文档注释可以嵌套多行注释。(错误,文档注释内的多行注释会被识别为结束符)
- 解析:多行注释
/* */不能嵌套,否则第一个*/会被识别为注释结束,导致编译报错。
二、填空题
- Scala 源程序文件的后缀是
.scala, Scala 字节码文件的后缀名称是.class。 - Scala 程序实现可移植性,依靠的是JVM(Java 虚拟机)。
三、简答题
简述 Scala 实现可移植性的基本原理。
答:Scala 代码会通过
scalac编译器编译成与 Java 完全兼容的 JVM 字节码文件(.class),字节码文件不依赖于具体的操作系统,仅运行在 JVM 之上。不同的操作系统都有对应的 JVM 实现,JVM 负责将字节码翻译成对应操作系统的机器指令执行,因此 Scala 程序只需一次编译,即可在所有安装了 JVM 的平台上运行,实现了可移植性。简述 Java 中 Path 的作用。
答:Path 是 Windows/Linux 系统的环境变量,作用是告诉操作系统,当执行一个命令时,去哪里查找对应的可执行程序。
- 配置 JDK 的 Path 后,在任意目录都可以执行
java、javac命令,无需输入全路径。 - 配置 Scala 的 Path 后,在任意目录都可以执行
scala、scalac命令,无需进入 Scala 的 bin 目录。
- 配置 JDK 的 Path 后,在任意目录都可以执行
简述 Scala 中标识符的组成。
答:Scala 的标识符分为 4 大类,具体组成规则如下:
- 字母数字标识符:以字母、下划线开头,后续可跟字母、数字、下划线,不能以数字开头,不能是 Scala 关键字。
- 运算符标识符:由一个或多个运算符字符(+、-、*、/、:、? 等)组成。
- 混合标识符:由字母数字标识符 + 下划线 + 运算符标识符组成。
- 字面量标识符:用反引号包裹的任意字符串,即使是 Scala 关键字也可作为标识符。
val 和 var 定义变量的区别?
答:val 和 var 是 Scala 声明变量 / 常量的两个核心关键字,核心区别如下:
表格
特性 val var 定义 声明不可变常量 声明可变变量 赋值规则 声明时必须初始化,赋值后不可修改 声明时必须初始化,赋值后可多次修改 修饰对象 引用地址 / 值不可变,对象内部的 var 属性可修改 引用地址和对象内部属性均可修改 线程安全 不可变,天然线程安全,并行场景无风险 可变,多线程场景需保证线程安全 开发规范 优先使用,大数据并行计算场景首选 仅在需要修改值时使用
四、编程题
需求
用 Scala 编写一个注册类,含有用户名和密码两个属性,要求:
用户名不可修改;
密码可修改。
在 REPL 分别输出原始信息 (用户名和密码) 和修改后的信息。
完整代码实现
/**
* 用户注册类
* @param username 用户名,val修饰,不可修改
* @param password 密码,var修饰,可修改
*/
class UserRegister(val username: String, var password: String) {
// 打印用户信息的方法
def showInfo(): Unit = {
println(s"用户名:$username,密码:$password")
}
}
// 单例对象,用于测试
object UserRegisterTest {
def main(args: Array[String]): Unit = {
// 创建用户对象
val user = new UserRegister("zhangsan", "123456")
// 打印原始信息
println("=== 原始信息 ===")
user.showInfo()
// 修改密码
user.password = "654321"
// 打印修改后的信息
println("=== 修改密码后的信息 ===")
user.showInfo()
}
}REPL 中执行步骤
- 将上述代码保存为
UserRegister.scala,在 REPL 中加载:
scala> :load UserRegister.scala
Loading UserRegister.scala...
defined class UserRegister
defined object UserRegisterTest- 创建用户对象,打印原始信息:
scala> val user = new UserRegister("lisi", "111111")
user: UserRegister = UserRegister@6d538012
scala> println("=== 原始信息 ===")
=== 原始信息 ===
scala> user.showInfo()
用户名:lisi,密码:111111- 修改密码,打印修改后的信息:
scala> user.password = "222222"
user.password: String = 222222
scala> println("=== 修改后的信息 ===")
=== 修改后的信息 ===
scala> user.showInfo()
用户名:lisi,密码:222222学习总结
- Scala 是运行在 JVM 上的多范式编程语言,融合了面向对象与函数式编程,是大数据 Spark/Flink 开发的核心语言,与 Java 完全无缝兼容。
- Scala 的编译运行原理与 Java 一致,
scalac编译源码为.class 字节码,scala命令运行字节码,REPL 交互式终端适合新手快速学习验证。 - Scala 的标识符规则比 Java 更灵活,支持运算符标识符、字面量标识符,具备自动分号推断能力,代码更简洁。
val和var是 Scala 变量的核心,val不可变常量是函数式编程的基础,大数据并行场景优先使用val,var仅在需要修改值时使用。lazy懒加载变量可延迟初始化,优化程序性能,是解决 Scala 继承空指针问题的核心手段。
下一章预习内容:Scala 的数据类型与基本运算,为后续 Scala 集合、函数式编程、大数据开发打下基础。