当前位置: 首页 > article >正文

Scala 入门指南

Scala 入门指南

目录

  • 简介
  • 环境搭建
  • 基础语法
  • 面向对象编程
  • 函数式编程
  • 集合
  • 模式匹配
  • 特质
  • 隐式转换
  • 并发编程
  • 与 Java 互操作
  • 最佳实践
  • 常见问题

简介

Scala 是一种多范式编程语言,结合了面向对象编程和函数式编程的特性。它运行在 JVM 上,与 Java 完全兼容,并且可以调用 Java 库。

Scala 的主要特性

  • 面向对象和函数式编程的结合
  • 静态类型系统
  • 类型推断
  • 模式匹配
  • 高阶函数
  • 不可变数据结构
  • 并发编程支持
  • 与 Java 互操作

环境搭建

1. 安装 JDK

Scala 需要 JDK 环境,推荐使用 JDK 8 或更高版本。

# 检查 Java 版本
java -version

2. 安装 Scala

方法一:使用 SDKMAN(推荐)
# 安装 SDKMAN
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"# 安装 Scala
sdk install scala
方法二:直接下载安装

从 Scala 官网 下载安装包并安装。

3. 安装 IDE

推荐使用 IntelliJ IDEA 或 VS Code 配合 Scala 插件。

IntelliJ IDEA
  1. 下载并安装 IntelliJ IDEA
  2. 安装 Scala 插件:File → Settings → Plugins → 搜索 “Scala” → 安装
  3. 重启 IDE
VS Code
  1. 安装 VS Code
  2. 安装 “Scala (Metals)” 插件
  3. 安装 “Scala Syntax (official)” 插件

4. 验证安装

# 检查 Scala 版本
scala -version# 启动 Scala REPL
scala

基础语法

1. 变量和常量

// 变量(可变)
var x = 10
x = 20  // 可以修改// 常量(不可变)
val y = 30
// y = 40  // 编译错误,不能修改// 类型声明(可选)
val name: String = "Scala"
var age: Int = 25

2. 基本数据类型

// 数值类型
val byte: Byte = 127
val short: Short = 32767
val int: Int = 2147483647
val long: Long = 9223372036854775807L
val float: Float = 3.14f
val double: Double = 3.141592653589793// 字符
val char: Char = 'A'// 布尔值
val boolean: Boolean = true// 字符串
val string: String = "Hello, Scala!"

3. 字符串操作

val name = "Scala"
val version = 3.0// 字符串插值
val message = s"$name version $version"
val message2 = s"${name.toUpperCase} version ${version + 0.1}"// 多行字符串
val multiline = """|This is a|multiline|string|""".stripMargin

4. 运算符

// 算术运算符
val a = 10
val b = 3
val sum = a + b
val diff = a - b
val product = a * b
val quotient = a / b
val remainder = a % b// 比较运算符
val isEqual = a == b
val isNotEqual = a != b
val isGreater = a > b
val isLess = a < b
val isGreaterOrEqual = a >= b
val isLessOrEqual = a <= b// 逻辑运算符
val p = true
val q = false
val and = p && q
val or = p || q
val not = !p

5. 条件语句

// if-else 语句
val age = 20
val status = if (age >= 18) "成年" else "未成年"// 多分支 if-else
val grade = 85
val level = if (grade >= 90) "A"else if (grade >= 80) "B"else if (grade >= 70) "C"else if (grade >= 60) "D"else "F"

6. 循环

// for 循环
for (i <- 1 to 5) {println(i)
}// 带过滤器的 for 循环
for (i <- 1 to 10 if i % 2 == 0) {println(i)
}// for 推导式
val squares = for (i <- 1 to 5) yield i * i// while 循环
var i = 1
while (i <= 5) {println(i)i += 1
}// do-while 循环
var j = 1
do {println(j)j += 1
} while (j <= 5)

面向对象编程

1. 类定义

// 简单类
class Person {var name: String = ""var age: Int = 0def sayHello(): Unit = {println(s"Hello, my name is $name and I am $age years old.")}
}// 主构造函数
class Person(val name: String, var age: Int) {def sayHello(): Unit = {println(s"Hello, my name is $name and I am $age years old.")}
}// 辅助构造函数
class Person {var name: String = ""var age: Int = 0def this(name: String) {this()this.name = name}def this(name: String, age: Int) {this(name)this.age = age}
}

2. 对象(单例)

// 单例对象
object Singleton {def sayHello(): Unit = {println("Hello from singleton!")}
}// 伴生对象
class Person(val name: String) {def sayHello(): Unit = {println(s"Hello, my name is $name")}
}object Person {def apply(name: String): Person = new Person(name)def unapply(person: Person): Option[String] = Some(person.name)
}

3. 继承

// 基类
class Animal(val name: String) {def makeSound(): Unit = {println("Some sound")}
}// 子类
class Dog(name: String) extends Animal(name) {override def makeSound(): Unit = {println("Woof!")}
}// 抽象类
abstract class Shape {def area(): Doubledef perimeter(): Double
}class Circle(radius: Double) extends Shape {def area(): Double = Math.PI * radius * radiusdef perimeter(): Double = 2 * Math.PI * radius
}

4. 封装

class BankAccount {private var balance = 0.0def deposit(amount: Double): Unit = {if (amount > 0) {balance += amount}}def withdraw(amount: Double): Boolean = {if (amount > 0 && amount <= balance) {balance -= amounttrue} else {false}}def getBalance: Double = balance
}

函数式编程

1. 函数定义

// 基本函数
def add(x: Int, y: Int): Int = x + y// 无参数函数
def getCurrentTime(): Long = System.currentTimeMillis()// 默认参数
def greet(name: String, greeting: String = "Hello"): String = {s"$greeting, $name!"
}// 命名参数
def createPerson(name: String, age: Int, city: String): String = {s"$name is $age years old and lives in $city"
}val person = createPerson(name = "Alice", age = 30, city = "New York")

2. 高阶函数

// 函数作为参数
def applyOperation(x: Int, f: Int => Int): Int = f(x)val double = (x: Int) => x * 2
val square = (x: Int) => x * xval result1 = applyOperation(5, double)  // 10
val result2 = applyOperation(5, square)  // 25// 函数作为返回值
def multiplier(factor: Int): Int => Int = {(x: Int) => x * factor
}val multiplyByTwo = multiplier(2)
val result3 = multiplyByTwo(5)  // 10

3. 匿名函数

// 基本匿名函数
val add = (x: Int, y: Int) => x + y// 简写形式
val numbers = List(1, 2, 3, 4, 5)
val doubled = numbers.map(x => x * 2)
val evenNumbers = numbers.filter(_ % 2 == 0)// 部分应用函数
val sum = (a: Int, b: Int, c: Int) => a + b + c
val addOneAndTwo = sum(1, 2, _)
val result = addOneAndTwo(3)  // 6

4. 柯里化

// 柯里化函数
def add(x: Int)(y: Int): Int = x + yval addOne = add(1)_
val result = addOne(5)  // 6// 非柯里化转柯里化
def nonCurriedAdd(x: Int, y: Int): Int = x + y
def curriedAdd = (nonCurriedAdd _).curried

集合

1. 不可变集合

// List
val list = List(1, 2, 3, 4, 5)
val first = list.head
val rest = list.tail
val newList = 0 :: list  // 在头部添加元素
val concatenated = list ++ List(6, 7)  // 连接列表// Set
val set = Set(1, 2, 3, 3, 4, 4, 5)  // 结果为 Set(1, 2, 3, 4, 5)
val contains = set.contains(3)  // true
val newSet = set + 6  // 添加元素// Map
val map = Map("a" -> 1, "b" -> 2, "c" -> 3)
val value = map("a")  // 1
val valueOrDefault = map.getOrElse("d", 0)  // 0
val newMap = map + ("d" -> 4)  // 添加键值对

2. 可变集合

import scala.collection.mutable// 可变 ListBuffer
val buffer = mutable.ListBuffer(1, 2, 3)
buffer += 4  // 添加元素
buffer -= 2  // 移除元素// 可变 Set
val mutableSet = mutable.Set(1, 2, 3)
mutableSet += 4  // 添加元素
mutableSet -= 2  // 移除元素// 可变 Map
val mutableMap = mutable.Map("a" -> 1, "b" -> 2)
mutableMap("c") = 3  // 添加或更新键值对
mutableMap -= "a"  // 移除键值对

3. 集合操作

val numbers = List(1, 2, 3, 4, 5)// 映射
val doubled = numbers.map(_ * 2)  // List(2, 4, 6, 8, 10)// 过滤
val evenNumbers = numbers.filter(_ % 2 == 0)  // List(2, 4)// 扁平化
val nestedList = List(List(1, 2), List(3, 4), List(5))
val flattened = nestedList.flatten  // List(1, 2, 3, 4, 5)// 扁平映射
val flatMapped = nestedList.flatMap(identity)  // List(1, 2, 3, 4, 5)// 折叠
val sum = numbers.foldLeft(0)(_ + _)  // 15
val product = numbers.foldRight(1)(_ * _)  // 120// 归约
val max = numbers.reduce((a, b) => if (a > b) a else b)  // 5

模式匹配

1. 基本模式匹配

def matchNumber(x: Int): String = x match {case 0 => "zero"case 1 => "one"case 2 => "two"case _ => "many"
}// 匹配多个值
def matchMultiple(x: Int): String = x match {case 0 | 1 | 2 => "small"case 3 | 4 | 5 => "medium"case _ => "large"
}

2. 类型模式匹配

def matchType(x: Any): String = x match {case s: String => s"String: $s"case i: Int => s"Integer: $i"case d: Double => s"Double: $d"case _ => "Unknown type"
}

3. 序列模式匹配

def matchList(list: List[Int]): String = list match {case Nil => "Empty list"case List(x) => s"Single element: $x"case List(x, y) => s"Two elements: $x and $y"case x :: rest => s"First element: $x, rest: $rest"
}

4. 样例类模式匹配

// 定义样例类
case class Person(name: String, age: Int)
case class Dog(name: String, breed: String)// 模式匹配
def matchPerson(person: Any): String = person match {case Person(name, age) => s"Person: $name, $age years old"case Dog(name, breed) => s"Dog: $name, breed: $breed"case _ => "Unknown"
}

特质

1. 基本特质

// 定义特质
trait Speaker {def speak(): String
}// 实现特质
class Dog extends Speaker {def speak(): String = "Woof!"
}class Cat extends Speaker {def speak(): String = "Meow!"
}

2. 带实现的特质

trait Animal {def name: Stringdef makeSound(): Stringdef description(): String = s"$name says ${makeSound()}"
}class Dog(val name: String) extends Animal {def makeSound(): String = "Woof!"
}class Cat(val name: String) extends Animal {def makeSound(): String = "Meow!"
}

3. 特质叠加

trait Logging {def log(msg: String): Unit = println(s"Log: $msg")
}trait TimestampLogging extends Logging {override def log(msg: String): Unit = {val timestamp = java.time.Instant.now()super.log(s"[$timestamp] $msg")}
}trait ShortLogging extends Logging {override def log(msg: String): Unit = {if (msg.length > 20) {super.log(msg.substring(0, 20) + "...")} else {super.log(msg)}}
}// 特质叠加顺序从右到左
class MyClass extends ShortLogging with TimestampLogging {def doSomething(): Unit = {log("This is a very long message that should be shortened")}
}

隐式转换

1. 基本隐式转换

// 定义隐式转换
implicit def intToString(x: Int): String = x.toString// 使用隐式转换
val str: String = 42  // 自动转换为 "42"

2. 隐式参数

// 定义带有隐式参数的函数
def greet(name: String)(implicit greeting: String): String = {s"$greeting, $name!"
}// 定义隐式值
implicit val defaultGreeting: String = "Hello"// 使用隐式参数
val message = greet("Alice")  // "Hello, Alice!"// 显式提供参数
val customMessage = greet("Bob")("Hi")  // "Hi, Bob!"

3. 类型类

// 定义类型类
trait Show[A] {def show(a: A): String
}// 为 Int 实现类型类
implicit val intShow: Show[Int] = new Show[Int] {def show(a: Int): String = a.toString
}// 为 String 实现类型类
implicit val stringShow: Show[String] = new Show[String] {def show(a: String): String = a
}// 使用类型类
def printValue[A](a: A)(implicit show: Show[A]): Unit = {println(show.show(a))
}printValue(42)  // 打印 "42"
printValue("Hello")  // 打印 "Hello"

并发编程

1. Future

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global// 创建 Future
val future = Future {Thread.sleep(1000)42
}// 处理 Future 结果
future.onComplete {case scala.util.Success(value) => println(s"Result: $value")case scala.util.Failure(exception) => println(s"Error: ${exception.getMessage}")
}// 使用 map 和 flatMap
val futureResult = future.map(_ * 2).map(_.toString)// 使用 for 推导式
val combinedFuture = for {a <- Future { 10 }b <- Future { 20 }
} yield a + b

2. Actor 模型(Akka)

import akka.actor.{Actor, ActorSystem, Props}// 定义 Actor
class Greeter extends Actor {def receive = {case "hello" => println("Hello, world!")case msg: String => println(s"Received: $msg")case _ => println("Unknown message")}
}// 创建 Actor 系统
val system = ActorSystem("MySystem")
val greeter = system.actorOf(Props[Greeter], "greeter")// 发送消息
greeter ! "hello"
greeter ! "How are you?"// 关闭系统
system.terminate()

与 Java 互操作

1. 调用 Java 代码

// 导入 Java 类
import java.util.Date// 创建 Java 对象
val date = new Date()
println(date)// 调用 Java 方法
val list = new java.util.ArrayList[String]()
list.add("Scala")
list.add("Java")
println(list)

2. Java 调用 Scala 代码

// Scala 类
class ScalaClass(val name: String) {def greet(): String = s"Hello from $name"
}// 伴生对象
object ScalaClass {def create(name: String): ScalaClass = new ScalaClass(name)
}
// Java 代码
ScalaClass scala = ScalaClass.create("Scala");
String greeting = scala.greet();
System.out.println(greeting);

最佳实践

1. 代码风格

  • 使用驼峰命名法
  • 类名首字母大写
  • 方法名首字母小写
  • 使用有意义的变量名
  • 适当添加注释

2. 函数式编程原则

  • 优先使用不可变数据
  • 使用纯函数
  • 避免副作用
  • 使用高阶函数和组合

3. 错误处理

// 使用 Option
def divide(a: Int, b: Int): Option[Int] = {if (b != 0) Some(a / b) else None
}// 使用 Try
import scala.util.Trydef safeDivide(a: Int, b: Int): Try[Int] = Try(a / b)// 使用 Either
def parseNumber(s: String): Either[String, Int] = {try {Right(s.toInt)} catch {case _: NumberFormatException => Left(s"Invalid number: $s")}
}

常见问题

1. 编译错误

  • 类型不匹配
  • 缺少分号
  • 括号不匹配
  • 导入错误

2. 运行时错误

  • 空指针异常
  • 类型转换错误
  • 并发问题

3. 性能问题

  • 内存泄漏
  • 过度使用递归
  • 集合操作效率

4. 调试技巧

  • 使用 println 调试
  • 使用 IDE 调试器
  • 使用日志框架
  • 单元测试

学习资源

  • Scala 官方文档
  • Scala School
  • Scala 编程(书籍)
  • Scala 函数式编程(书籍)
  • Coursera Scala 课程

相关文章:

Scala 入门指南

Scala 入门指南 目录 简介环境搭建基础语法面向对象编程函数式编程集合模式匹配特质隐式转换并发编程与 Java 互操作最佳实践常见问题 简介 Scala 是一种多范式编程语言&#xff0c;结合了面向对象编程和函数式编程的特性。它运行在 JVM 上&#xff0c;与 Java 完全兼容&am…...

[密码学实战]密评考试训练系统v1.0程序及密评参考题库(获取路径在文末)

[密码学实战]密评考试训练系统v1.0程序及密评参考题库 引言:密评考试的重要性与挑战 商用密码应用安全性评估(简称"密评") 作为我国密码领域的重要认证体系,已成为信息安全从业者的必备技能。根据国家密码管理局最新数据,截至2024年6月,全国仅有3000余人持有…...

【Rust 精进之路之第6篇-流程之舞】控制流:`if/else`, `loop`, `while`, `for` 与模式匹配初窥

系列: Rust 精进之路:构建可靠、高效软件的底层逻辑 作者: 码觉客 发布日期: 2025-04-20 引言:让代码“活”起来——指令的流动 在前面的文章中,我们已经掌握了 Rust 的基础数据类型(标量和复合类型)以及如何通过变量绑定来存储和命名它们。这相当于我们准备好了程序…...

Git ——提交至github,Vercel拉取,更新不了项目的问题解决

首先因为github上有个错误 1 failing check Vercel - No GitHub account was found matching the commit author email address 发现好像是vercel拉取不了项目&#xff0c;vercel登录的邮箱与我此次提交更改的邮箱不匹配&#xff0c;查看Git的user确实如此&#xff08;之前的…...

原型模式详解及在自动驾驶场景代码示例(c++代码实现)

模式定义 原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;通过克隆已有对象来创建新对象&#xff0c;避免重复执行昂贵的初始化操作。该模式特别适用于需要高效创建相似对象的场景&#xff0c;是自动驾驶感知系统中处理大量重复数据结构的…...

蓝桥杯常考的找规律题

目录 灵感来源&#xff1a; B站视频链接&#xff1a; 找规律题具有什么样的特点&#xff1a; 报数游戏&#xff08;Java组&#xff09;&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路详解&#xff1a; 代码详解&#xff1a; 阶乘求和&#xff08;Java组…...

MySQL_MCP_Server_pro接入cherry_studio实现大模型操作数据库

大模型直接与数据库交互&#xff0c;实现基本增删改查操作。首先贴下代码地址&#xff1a; https://github.com/wenb1n-dev/mysql_mcp_server_pro 安装环境&#xff1a;win10 1、下载代码 git clone https://github.com/wenb1n-dev/mysql_mcp_server_pro 2、使用conda创建…...

Element UI、Element Plus 里的表单验证的required必填的属性不能动态响应?

一 问题背景 想要实现&#xff1a; 新增/修改对话框中(同一个)&#xff0c;修改时“备注”字段非必填&#xff0c;新增时"备注"字段必填 结果发现直接写不生效-初始化一次性 edit: [{ required: true, message: "请输入备注", trigger: "blur" }…...

Spark-Streaming

WordCount案例 添加依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"…...

transformer 子层连接结构

子层连接结构 目标 了解什么是子层连接结构掌握子层连接结构的实现过程 什么是子层连接结构? 输入到每个子层以及规范化层的过程中, 使用了残差连接(跳跃连接, 从Add&Norm -> Add&Norm), 因此我们把这一部分结构整体叫做子层连接(代表子层及其链接结构), 在每个…...

linux oracle 19c 静默安装

oracle数据库有个比较很抓瞎的事情&#xff0c;不同的版本搭建的大致流程是一样的&#xff0c;但是在实操细节上会有不同&#xff0c;比如操作的脚本位置和配置项等等&#xff0c;这些会变&#xff0c;所以需要时常积累不同版本的文档 这里有一点要说明&#xff0c;之所以使用…...

C++ 的 输入输出流(I/O Streams)

什么是输入输出流 C 的输入输出操作是通过 流&#xff08;stream&#xff09; 机制实现的。 流——就是数据的流动通道&#xff0c;比如&#xff1a; 输入流&#xff1a;从设备&#xff08;如键盘、文件&#xff09;读取数据 → 程序 输出流&#xff1a;程序将数据写入设备&…...

mybatis-plus开发orm

1、mybatis 使用mybatis-generator自动生成代码 这个也是有系统在使用 2、mybatis-plus开发orm--有的系统在使用 MybatisPlus超详细讲解_mybatis-plus-CSDN博客...

使用Python+OpenCV将多级嵌套文件夹下的视频文件抽帧为JPG图片

使用PythonOpenCV将多级嵌套文件夹下的视频文件抽帧为JPG图片 import os import cv2 import time# 存放视频文件的多层嵌套文件夹路径 videoPath D:\\videos\\ # 保存抽帧的图片的文件夹路径 savePath D:\\images\\if not os.path.exists(savePath):os.mkdir(savePath) vide…...

电子电器架构 --- DFMEA设计失效模式和后果分析

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…...

C#抽象类和虚方法的作用是什么?

抽象类 (abstract class)&#xff1a; 不能直接实例化&#xff0c;只能被继承。 用来定义一套基础框架和规范&#xff0c;强制子类必须实现某些方法&#xff08;抽象方法&#xff09;。 可用来封装一些共通的逻辑&#xff0c;减少代码重复。 虚方法 (virtual)&#xff1a; …...

C#获取当前方法的命名空间、类名称、方法名称以及方法的参数信息

C#获取当前方法的命名空间、类名称、方法名称以及方法的参数信息 输出示例模块示例 输出示例 获取信息&#xff1a;WindowsFormsApp1.Form1.button1_Click(System.Object sender,System.EventArgs e) 引发的异常:“System.IndexOutOfRangeException”(位于 WindowsFormsApp1.ex…...

Apache SeaTunnel:新一代开源、高性能数据集成工具

Apache SeaTunnel 是一款开源、分布式、高性能的数据集成工具&#xff0c;可以通过配置快速搭建数据管道&#xff0c;支持实时海量数据同步。 Apache SeaTunnel 专注于数据集成和数据同步&#xff0c;主要旨在解决数据集成领域的常见问题&#xff1a; 数据源多样性&#xff1a…...

python+selenium+pytest自动化测试chrome driver版本下载

chrome浏览器chromedriver版本下载地址 https://googlechromelabs.github.io/chrome-for-testing/#stable...

3.1 WPF使用MaterialDesign的介绍1

MaterialDesignInXAML Toolkit 是一个流行的开源 C# WPF 控件库,它实现了 Google 的 Material Design 规范,让开发者可以轻松创建现代化的 WPF 应用程序界面 Material Design 是一个流行的设计语言,由 Google 开发,旨在帮助开发者构建美观且一致的 UI 界面。对于使用 C# 的…...

从 0 到 1 打通 AI 工作流:Dify+Zapier 实现工具自动化调用实战

一、引言&#xff1a;当 AI 遇到工具孤岛 在企业数字化转型的浪潮中&#xff0c;AI 工具的应用早已从单一的对话交互进阶到复杂的业务流程自动化。但开发者常常面临这样的困境&#xff1a;本地开发的 MCP 工具&#xff08;如 ERP 数据清洗脚本、CRM 工单系统 API&#xff09;如…...

【算法笔记】如何优雅的进行字符串操作

最近的CCCC天梯赛又出了非常恶心的字符串题~ 在编程竞赛&#xff08;特别是CCCC天梯赛&#xff09;中&#xff0c;字符串操作类题目往往看似简单却暗藏陷阱。本文将以Python、Java、C 三剑客为例&#xff0c;总结高频字符串操作的优雅实现方案&#xff0c;助你快速攻克字符串类…...

docker转移镜像

1、场景 有网络环境向无网络环境转移镜像。无法拉取的镜像&#xff08;外网无法访问&#xff09;下载镜像转移到服务器上。 2、docker转移 2.1 镜像服务器 保存镜像 列出项目使用的所有镜像 docker images 保存所有镜像为 tar 文件 保存docker镜像 docker save -o my_…...

【Rust 精进之路之第12篇-生命周期·入门】为何需要与显式标注 (`‘a`):让编译器读懂引用的“有效期”

系列: Rust 精进之路:构建可靠、高效软件的底层逻辑 作者: 码觉客 发布日期: 2025-04-20 引言:悬垂引用的“幽灵”与编译器的“侦探” 在前面的章节中,我们深入学习了 Rust 的所有权系统,以及如何通过引用 (& 和 &mut) 进行借用,从而在不转移所有权的情况下安…...

Vue.js 之 `v-for` 命令详解

Vue.js 之 v-for 命令详解 在 Vue.js 中&#xff0c;v-for 是一个非常强大的指令&#xff0c;用于遍历数组或对象中的数据&#xff0c;并渲染相应的 DOM 元素。无论是在列表展示、表单生成还是动态组件加载中&#xff0c;v-for 都发挥着重要作用。本文将详细介绍 v-for 的用法…...

Spring Boot中`logging.config`配置项的详解及使用说明

以下是Spring Boot中logging.config配置项的详解及使用说明&#xff1a; 1. logging.config 作用 功能&#xff1a;指定自定义日志配置文件的路径&#xff0c;覆盖Spring Boot默认的日志配置。适用场景&#xff1a;当需要深度定制日志行为&#xff08;如输出格式、文件路径、…...

相机模型--CMOS和CCD的区别

1--CMOS和CCD的工作原理 CCD&#xff08;Charge Coupled Device&#xff0c;电荷耦合器件&#xff09;&#xff1a; 1. 图像通过光电效应在感光单元中转化为电荷&#xff1b; 2. 每个像素上的电荷被依次“耦合”并传输到芯片的角落&#xff0c;通过一个或几个模拟输出放大器输…...

el-date-picker时间范围 赋值报错问题

问题&#xff1a; 点击时间范围组件右边清除图标&#xff0c;点击近6小时会把设置好的时间赋值给时间范围组件 但是出现报错 原因&#xff1a; 尝试对null值进行属性设置操作&#xff1a;修改一个数组的元素&#xff0c;但此时这个数组是null&#xff0c;而不是预期的数组类型…...

为啥低速MCU单板辐射测试会有200M-1Ghz的辐射信号

低速MCU&#xff08;如8位或16位单片机&#xff09;单板在辐射测试中出现 200MHz~1GHz的高频辐射信号&#xff0c;看似不合理&#xff0c;但实际上是由多种因素共同导致的。以下是详细原因分析及解决方案&#xff1a; 1.根本原因分析: (1) 时钟谐波与开关噪声 低速MCU的时钟谐…...

【音视频】FFmpeg解封装

解封装 复用器&#xff0c;比如MP4/FLV 解复用器&#xff0c;MP4/FLV 封装格式相关函数 avformat_alloc_context(); 负责申请一个AVFormatContext结构的内存,并进行简单初始化avformat_free_context(); 释放该结构里的所有东西以及该结构本身avformat_close_input();关闭解复…...