第1章 Scala 入门与环境

Scala 是什么、为什么值钱(Spark / Flink 都在用它)、环境怎么装、第一个程序怎么写。

入门第1周2 讲6 段示例代码

本章学习目标

  • 能说出 Scala 与 Java 的关系,以及它在 JVM 生态里的位置
  • 能区分函数式与面向对象两种写法,并知道 Scala 两者都支持
  • 能装好 JDK + sbt / scala-cli,跑通第一个 HelloWorld
  • 会用 REPL 做小段试验

本章导览

核心内容

1.1

Scala 是什么:JVM 上的函数式 + 面向对象

看清 Scala 的定位:JVM 上的函数式与面向对象合体。

能说出 Scala 与 Java、JVM 的关系能各举一个函数式与面向对象的 Scala 写法知道这门课用 Scala 2.13 + sbt 来练手

知识点

一门跑在 JVM 上的静态语言

  • Scala 源码编译成 JVM 字节码,能直接调用 Java 类库。
  • 静态类型:类型错误在编译期暴露,不等到运行时才炸。
  • 同时支持面向对象与函数式,两种风格可以在一个文件里混写。

和 Java 像,但不是 Java 方言

  • object 定义单例,val 定义不可变值,def 定义方法,语法比 Java 紧凑。
  • Java 的类、接口、集合在 Scala 里都能用,Scala 类也能被 Java 调用。
  • 没有 static、没有 i++、没有三目运算符,对应写法后面会逐一讲。

为什么值得学

  • Spark、Kafka 等组件大量使用 Scala,Flink 也提供 Scala API,读源码和调 API 常常绕不开它。
  • 函数式写法让集合处理、并发和测试更简单,表达力强。
  • 代价是类型系统和隐式规则学习曲线陡,前期先把语法用熟。

本课版本口径

  • 全课以 Scala 2.13 + sbt 为准,示例都在 2.13 上编译运行。
  • 遇到 Scala 3 不同处(given/using、缩进语法、enum)会单独注明,不混用两种语法。

代码示例

▶ REPL 初体验:集合操作与样例类
SCALA
$ scala
scala> val nums = List(1, 2, 3, 4)
nums: List[Int] = List(1, 2, 3, 4)

scala> nums.filter(_ % 2 == 0).map(_ * 10)
res0: List[Int] = List(20, 40)

scala> case class User(name: String, age: Int)
defined class User

scala> User("小明", 18).copy(age = 19)
res1: User = User(小明,19)
👀 运行结果
List(1, 2, 3, 4)
List(20, 40)
defined class User
User(小明,19)
▶ 直接调用 Java 的集合类
SCALA
object Interop {
  def main(args: Array[String]): Unit = {
    val list = new java.util.ArrayList[String]()
    list.add("a")
    list.add("b")
    println(list.size())
    println(list)
  }
}
👀 运行结果
2
[a, b]
▶ 递归 + if 表达式:一个方法完成阶乘
SCALA
object Factorial {
  def fact(n: Int): Int =
    if (n <= 1) 1 else n * fact(n - 1)

  def main(args: Array[String]): Unit =
    println(fact(5))
}
👀 运行结果
120

常见错误

⚠️ 踩坑与解决
  • 在 .scala 文件顶层直接写 def main,报 expected class or object definition
    → Scala 2 的源文件顶层只允许 package、class、object、trait,顶层方法没有宿主。;把代码包进 object,例如 object Hello { def main(args: Array[String]): Unit = ... },或先在 REPL 里试。
  • PowerShell 输入 scala 提示“无法将 scala 项识别为 cmdlet”
    → 没装 Scala 发行版,或者安装目录没有加进 PATH。;先用 sbt console 启动 REPL;或安装 Scala CLI 后重开终端再执行 scala-cli。

💡 把 REPL 当草稿纸:语法拿不准就先敲两行验证,再写进文件。

1.2

环境搭建与第一个程序(JDK、sbt / scala-cli、IDEA、REPL)

装好 JDK 与 sbt,跑通 HelloWorld 和 REPL。

能检查 JDK 版本并配好 JAVA_HOME能用 sbt 运行一个 Scala 2.13 项目能在 REPL 里验证表达式与退出

知识点

JDK 是地基

  • Scala 编译器和程序都跑在 JVM 上,先装 JDK 11 或 17 这类 LTS 版本。
  • 命令行执行 java -version 和 javac -version,确认两个命令来自同一套 JDK。
  • 把 JAVA_HOME 指向 JDK 根目录,并把它的 bin 目录加进 PATH。

sbt 管项目

  • 项目根目录的 build.sbt 写 scalaVersion := "2.13.14",源码放在 src/main/scala。
  • sbt compile 编译,sbt run 运行,sbt console 进 REPL,sbt clean 清理。
  • 第一次运行会下载 sbt 插件和 Scala 依赖,网络慢时多等一会,不要急着改配置。

scala-cli 与 IDEA

  • 单个 .scala 文件用 scala-cli run Hello.scala 更轻,不必先建完整的 sbt 工程。
  • scala-cli 默认可能选 Scala 3;跑本课代码时加 --scala 2.13.14,避免语法对不上。
  • IDEA 装 Scala 插件后导入 sbt 项目,代码补全和调试更顺手。
  • 本课示例都能用 sbt 跑,build.sbt 里的 scalaVersion 固定为 2.13。

代码示例

▶ build.sbt 与 Hello.scala 分两个文件写:最小可运行项目
SCALA
// 文件 1:build.sbt
scalaVersion := "2.13.14"

// 文件 2:src/main/scala/Hello.scala
object Hello {
  def main(args: Array[String]): Unit = {
    println("你好,Scala 2.13")
  }
}
👀 运行结果
$ sbt run
[info] compiling 1 Scala source to ...\target\scala-2.13\classes ...
[info] running Hello
你好,Scala 2.13
[success] Total time: 1 s
▶ sbt console:不建类也能试语法
SCALA
$ sbt console
scala> val name = "Scala"
name: String = Scala

scala> s"Hello, $name!"
res0: String = Hello, Scala!

scala> List(1, 2, 3).sum
res1: Int = 6

scala> :quit
👀 运行结果
name: String = Scala
res0: String = Hello, Scala!
res1: Int = 6
▶ 给 main 传命令行参数
SCALA
object HelloArgs {
  def main(args: Array[String]): Unit = {
    val who = if (args.isEmpty) "world" else args.mkString(", ")
    println(s"Hello, $who!")
  }
}
👀 运行结果
$ sbt "run Alice Bob"
[info] running HelloArgs Alice Bob
Hello, Alice, Bob!
[success] Total time: 1 s

常见错误

⚠️ 踩坑与解决
  • 命令行提示 java 不是内部或外部命令
    → JDK 没装,或者 JAVA_HOME / PATH 没有配好。;安装 JDK 17,重新打开终端,用 java -version 和 javac -version 验证。
  • sbt run 报 [error] No main class detected
    → 当前项目没有带 main 方法的 object,或者源码没有放在 src/main/scala 下。;检查 object 里有 def main(args: Array[String]): Unit,文件在 src/main/scala,再执行 sbt run。

💡 第一次 sbt 会下载依赖和编译插件,卡几分钟很正常;先等它跑完,再判断是不是配置出错。