Scala基础知识
scala
1、scala简介
 scala是运行在JVM上的多范式编程语言,同时支持面向对象和面向函数式编程。
2、scala解释器
要启动scala解释器,只需要以下几步:
- 按住windows键 + r
- 输入scala即可

- 在scala命令提示窗口中执行:quit,即可退出解释器
3、scala的基本语法
3.1、声明变量
在scala中,可以使用val或者var来定义变量,语法格式如下:
val/var 变量标识:变量类型 = 初始值
其中
- val定义的是不可重新赋值的变量
- var定义的是可重新赋值的变量
[!NOTE]
- scala中定义变量类型写在变量名后面
- scala的语句最后不需要添加分号
问题:val 和 var修饰的变量有什么区别?
3.2、字符串
scala提供多种定义字符串的方式,将来我们可以根据需要来选择最方便的定义方式。
-  使用双引号 val/var 变量名 = “字符串”
-  使用插值表达式 val/var 变量名 = s"${变量/表达式}字符串"
-  使用三引号 val/var 变量名 = """字符串1 字符串2"""
3.3、数据类型
| 基础类型 | 类型说明 | 
|---|---|
| Byte | 8位带符号整数 | 
| Short | 16位带符号整数 | 
| Int | 32位带符号整数 | 
| Long | 64位带符号整数 | 
| Char | 16位无符号Unicode字符 | 
| String | Char类型的序列(字符串) | 
| Float | 32位单精度浮点数 | 
| Double | 64位双精度浮点数 | 
| Boolean | true或false | 
注意下 scala类型与Java的区别
[!NOTE]
- scala中所有的类型都使用大写字母开头
- 整形使用
Int而不是Integer- scala中定义变量可以不写类型,让scala编译器自动推断
3.3.1、scala类型层次结构

3.4、表达式
3.4.1、条件表达式
条件表达式就是if表达式,if表达式可以根据给定的条件是否满足,根据条件的结果(真或假)决定执行对应的操作。
scala条件表达式的语法和Java一样。与Java不一样的是,
[!NOTE]
- 在scala中,条件表达式也是有返回值的
- 在scala中,没有三元表达式,可以使用if表达式替代三元表达式
3.4.2、块表达式
- scala中,使用{}表示一个块表达式
- 和if表达式一样,块表达式也是有值的
- 值就是最后一个表达式的值
问题
请问以下代码,变量a的值是什么?
scala> val a = {| println("1 + 1")| 1 + 1| }
3.5、循环
在scala中,可以使用for和while,但一般推荐使用for表达式,因为for表达式语法更简洁
3.5.1、for循环
语法
for(i <- 表达式/数组/集合) {// 表达式
}
3.5.2、嵌套for循环
使用for表达式,打印以下字符
*****
*****
*****
步骤
- 使用for表达式打印3行,5列星星
- 每打印5个星星,换行
参考代码
for(i <- 1 to 3; j <- 1 to 5) {print("*");if(j == 5) println("")}
3.5.3、while循环
scala中while循环和Java中是一致的
示例
打印1-10的数字
参考代码
scala> var i = 1
i: Int = 1scala> while(i <= 10) {| println(i)| i = i+1| }
3.6、方法
语法
def methodName (参数名:参数类型, 参数名:参数类型) : [return type] = {// 方法体:一系列的代码
}
[!NOTE]
- 参数列表的参数类型不能省略
- 返回值类型可以省略,由scala编译器自动推断
- 返回值可以不写return,默认就是{}块表达式的值
示例
- 定义一个方法,实现两个整形数值相加,返回相加后的结果
- 调用该方法
参考代码
scala> def add(a:Int, b:Int) = a + b
m1: (x: Int, y: Int)Intscala> add(1,2)
res10: Int = 3
3.6.1、方法参数
scala中的方法参数,使用比较灵活。它支持以下几种类型的参数:
- 默认参数
- 带名参数
- 变长参数
默认参数
在定义方法时可以给参数定义一个默认值。
示例
- 定义一个计算两个值相加的方法,这两个值默认为0
- 调用该方法,不传任何参数
参考代码
// x,y带有默认值为0 
def add(x:Int = 0, y:Int = 0) = x + y
add()
带名参数
在调用方法时,可以指定参数的名称来进行调用。
示例
- 定义一个计算两个值相加的方法,这两个值默认为0
- 调用该方法,只设置第一个参数的值
参考代码
def add(x:Int = 0, y:Int = 0) = x + y
add(x=1)
变长参数
如果方法的参数是不固定的,可以定义一个方法的参数是变长参数。
语法格式:
def 方法名(参数名:参数类型*):返回值类型 = {方法体
}
[!NOTE]
在参数类型后面加一个
*号,表示参数可以是0个或者多个
示例
- 定义一个计算若干个值相加的方法
- 调用方法,传入以下数据:1,2,3,4,5
参考代码
scala> def add(num:Int*) = num.sum
add: (num: Int*)Intscala> add(1,2,3,4,5)
res1: Int = 15
3.7、函数
语法
val 函数变量名 = (参数名:参数类型, 参数名:参数类型....) => 函数体
[!TIP]
- 函数是一个对象(变量)
- 类似于方法,函数也有输入参数和返回值
- 函数定义不需要使用
def定义- 无需指定返回值类型
示例
- 定义一个两个数值相加的函数
- 调用该函数
参考代码
scala> val add = (x:Int, y:Int) => x + y
add: (Int, Int) => Int = <function2>scala> add(1,2)
res3: Int = 3
4、数据结构
4.1、数组
定长数组
- 定长数组指的是数组的长度是不允许改变的
- 数组的元素是可以改变的
语法
// 通过指定长度定义数组
val/var 变量名 = new Array[元素类型](数组长度)// 用元素直接初始化数组
val/var 变量名 = Array(元素1, 元素2, 元素3...)
[!NOTE]
- 在scala中,数组的泛型使用
[]来指定- 使用
()来获取元素
变长数组
创建变长数组,需要提前导入ArrayBuffer类import scala.collection.mutable.ArrayBuffer
语法
-  创建空的ArrayBuffer变长数组,语法结构: val/var a = ArrayBuffer[元素类型]()
-  创建带有初始元素的ArrayBuffer val/var a = ArrayBuffer(元素1,元素2,元素3....)
数组的相关操作
- 使用+=添加元素
- 使用-=删除元素
- 使用++=追加一个数组到变长数组
- 使用for遍历数组
4.2、元组
元组可以用来包含一组不同类型的值。例如:姓名,年龄,性别,出生年月。元组的元素是不可变的。
语法
使用括号来定义元组
val/var 元组 = (元素1, 元素2, 元素3....)
使用箭头来定义元组(元组只有两个元素)
val/var 元组 = 元素1->元素2
示例
定义一个元组,包含一个学生的以下数据
| id | 姓名 | 年龄 | 地址 | 
|---|---|---|---|
| 1 | zhangsan | 20 | beijing | 
参考代码
scala> val a = (1, "zhangsan", 20, "beijing")
a: (Int, String, Int, String) = (1,zhangsan,20,beijing)
访问元组
使用_1、_2、_3…来访问元组中的元素,_1表示访问第一个元素,依次类推
示例
- 定义一个元组,包含一个学生的姓名和性别,“zhangsan”, “male”
- 分别获取该学生的姓名和性别
参考代码
scala> val a = "zhangsan" -> "male"
a: (String, String) = (zhangsan,male)// 获取第一个元素
scala> a._1
res41: String = zhangsan// 获取第二个元素
scala> a._2
res42: String = male
4.3、列表
不可变列表
语法
使用List(元素1, 元素2, 元素3, ...)来创建一个不可变列表,语法格式:
val/var 变量名 = List(元素1, 元素2, 元素3...)
使用Nil创建一个不可变的空列表
val/var 变量名 = Nil
使用::方法创建一个不可变列表
val/var 变量名 = 元素1 :: 元素2 :: Nil
[!TIP]
使用**::拼接方式来创建列表,必须在最后添加一个Nil
可变列表
可变列表就是列表的元素、长度都是可变的。
要使用可变列表,先要导入import scala.collection.mutable.ListBuffer
[!NOTE]
- 可变集合都在
mutable包中- 不可变集合都在
immutable包中(默认导入)
定义
使用ListBuffer[元素类型]()创建空的可变列表,语法结构:
val/var 变量名 = ListBuffer[Int]()
使用ListBuffer(元素1, 元素2, 元素3…)创建可变列表,语法结构:
val/var 变量名 = ListBuffer(元素1,元素2,元素3...)
可变列表的操作
- 获取元素(使用括号访问(索引值))
- 添加元素(+=)
- 追加一个列表(++=)
- 更改元素(使用括号获取元素,然后进行赋值)
- 删除元素(-=)
- 转换为List(toList)
- 转换为Array(toArray)
4.4、集合
Set(集)是代表没有重复元素的集合。Set具备以下性质:
- 元素不重复
- 不保证插入顺序
scala中的集也分为两种,一种是不可变集,另一种是可变集。
不可变集
语法
创建一个空的不可变集,语法格式:
val/var 变量名 = Set[类型]()
给定元素来创建一个不可变集,语法格式:
val/var 变量名 = Set(元素1, 元素2, 元素3...)
可变集
定义
可变集合不可变集的创建方式一致,只不过需要提前导入一个可变集类。
手动导入:import scala.collection.mutable.Set
4.5、映射
Map可以称之为映射。它是由键值对组成的集合。在scala中,Map也分为不可变Map和可变Map。
不可变Map
定义
语法
val/var map = Map(键->值, 键->值, 键->值...)	// 推荐,可读性更好
val/var map = Map((键, 值), (键, 值), (键, 值), (键, 值)...)
示例
1)定义一个映射,包含以下学生姓名和年龄数据
"zhangsan", 30
"lisi", 40
2)获取zhangsan的年龄
scala> val map = Map("zhangsan"->30, "lisi"->40)
map: scala.collection.mutable.Map[String,Int] = Map(lisi -> 40, zhangsan -> 30)// 获取zhangsan的年龄
scala> val age = map.get("zhangsan")
可变Map
定义
定义语法与不可变Map一致。但定义可变Map需要手动导入import scala.collection.mutable.Map
示例
1)定义一个映射,包含以下学生姓名和年龄数据
"zhangsan", 30
"lisi", 40
2)修改zhangsan的年龄为20
scala> val map = Map("zhangsan"->30, "lisi"->40)
map: scala.collection.mutable.Map[String,Int] = Map(lisi -> 40, zhangsan -> 30)// 修改value
scala> map("zhangsan") = 20
5、函数式编程
- 遍历(foreach)
- 映射(map)
- 映射扁平化(flatmap)
- 过滤(filter)
- 是否存在(exists)
- 排序(sorted、sortBy、sortWith)
- 分组(groupBy)
- 聚合计算(reduce)
- 折叠(fold)
6、伴生对象
一个class和object具有同样的名字。这个object称为伴生对象,这个class称为伴生类
- 伴生对象必须要和伴生类一样的名字
- 伴生对象和伴生类在同一个scala源文件中
- 伴生对象和伴生类可以互相访问private属性
参考代码
object _11ObjectDemo {class CustomerService {def save() = {println(s"${CustomerService.SERVICE_NAME}:保存客户")}}// CustomerService的伴生对象object CustomerService {private val SERVICE_NAME = "CustomerService"}def main(args: Array[String]): Unit = {val customerService = new CustomerService()customerService.save()}
}
7、样例类
样例类是一种特殊类,它可以用来快速定义一个用于保存数据的类(类似于Java POJO类)
语法格式
case class 样例类名(var/val 成员变量名1:类型1, 成员变量名2:类型2, 成员变量名3:类型3)
- 如果要实现某个成员变量可以被修改,可以添加var
- 默认为val,可以省略
需求
- 定义一个Person样例类,包含姓名和年龄成员变量
- 创建样例类的对象实例(“张三”、20),并打印它
参考代码
object _01CaseClassDemo {case class Person(name:String, age:Int)def main(args: Array[String]): Unit = {val zhangsan = Person("张三", 20)println(zhangsan)}
}
8、样例对象
它主要用在两个地方:
1)作为没有任何参数的消息传递
使用case object可以创建样例对象。样例对象是单例的,而且它没有主构造器
语法格式
case object 样例对象名
9、模式匹配
9.1、 简单模式匹配
语法格式
变量 match {case "常量1" => 表达式1case "常量2" => 表达式2case "常量3" => 表达式3case _ => 表达式4		// 默认配
}
示例
需求说明
1)从控制台输入一个单词(使用StdIn.readLine方法)
2)判断该单词是否能够匹配以下单词,如果能匹配,返回一句话
3)打印这句话
| 单词 | 返回 | 
|---|---|
| hadoop | 大数据分布式存储和计算框架 | 
| zookeeper | 大数据分布式协调服务框架 | 
| spark | 大数据分布式内存计算框架 | 
| 未匹配 | 未匹配 | 
参考代码
println("请输出一个词:")
// StdIn.readLine表示从控制台读取一行文本
val name = StdIn.readLine()val result = name match {case "hadoop" => "大数据分布式存储和计算框架"case "zookeeper" => "大数据分布式协调服务框架"case "spark" => "大数据分布式内存计算框架"case _ => "未匹配"
}println(result)
9.2、匹配样例类
scala可以使用模式匹配来匹配样例类,从而可以快速获取样例类中的成员数据。后续,我们在开发Akka案例时,还会用到。
示例
需求说明
- 创建两个样例类Customer、Order - Customer包含姓名、年龄字段
- Order包含id字段
 
- 分别定义两个案例类的对象,并指定为Any类型
- 使用模式匹配这两个对象,并分别打印它们的成员变量值
参考代码
// 1. 创建两个样例类
case class Person(name:String, age:Int)
case class Order(id:String)def main(args: Array[String]): Unit = {// 2. 创建样例类对象,并赋值为Any类型val zhangsan:Any = Person("张三", 20)val order1:Any = Order("001")// 3. 使用match...case表达式来进行模式匹配// 获取样例类中成员变量order1 match {case Person(name, age) => println(s"姓名:${name} 年龄:${age}")case Order(id1) => println(s"ID为:${id1}")case _ => println("未匹配")}
}
10、高阶函数
高阶函数包含
- 作为值的函数
- 匿名函数
- 闭包
- 柯里化等等
作为值的函数
示例说明
将一个整数列表中的每个元素转换为对应个数的小星星
List(1, 2, 3...) => *, **, *** 
步骤
- 创建一个函数,用于将数字装换为指定个数的小星星
- 创建一个列表,调用map方法
- 打印转换为的列表
参考代码
val func = (num:Int) => "*" * numprintln((1 to 10).map(func))
匿名函数
没有赋值给变量的函数就是匿名函数
参考代码
println((1 to 10).map(num => "*" * num))
// 因为此处num变量只使用了一次,而且只是进行简单的计算,所以可以省略参数列表,使用_替代参数
println((1 to 10).map("*" * _))
闭包
闭包其实就是一个函数,只不过这个函数的返回值依赖于声明在函数外部的变量。
可以简单认为,就是可以访问不在当前作用域范围的一个函数。
示例
定义一个闭包
val y=10val add=(x:Int)=>{x+y
}println(add(5)) // 结果15
add函数就是一个闭包
柯里化
柯里化(Currying)是指将原先接受多个参数的方法转换为多个参数列表的过程。
示例
示例说明
- 编写一个方法,用来完成两个Int类型数字的计算
- 具体如何计算封装到函数中
- 使用柯里化来实现上述操作
参考代码
// 柯里化:实现对两个数进行计算
def calc_carried(x:Double, y:Double)(func_calc:(Double, Double)=>Double) = {func_calc(x, y)
}def main(args: Intrray[String]): Unit = {println(calc_carried(10.1, 10.2){(x,y) => x + y})println(calc_carried(10, 10)(_ + _))println(calc_carried(10.1, 10.2)(_ * _))println(calc_carried(100.2, 10)(_ - _))
}
相关文章:
 
Scala基础知识
scala 1、scala简介  scala是运行在JVM上的多范式编程语言,同时支持面向对象和面向函数式编程。 2、scala解释器 要启动scala解释器,只需要以下几步: 按住windows键 r输入scala即可 在scala命令提示窗口中执行:quit,即可退…...
 
数学建模-------误差来源以及误差分析
绝对误差:精确值-近似值; 举个例子:从A到B,应该有73千米,但是我们近似成了70千米;从C到D,应该是1373千米,我们近似成了1370千米,如果使用绝对误差,结果都是3…...
Arduino和MPLAB X 开发STM32F103和PIC16F15376
要点: 使用Arduino开发STM32F103(Blue Pill),MPLAB X 开发PIC16F15376(Curiosity Nano)C/C嵌入式开发ESP32(Arduino、ESP-IDF)和STM32实时操作系统FreeRTOS STM32使用FreeRTOS示例 在使用 FreeRTOS 时&a…...
手机操作系统Android
▶1.Android系统概述 Andaid(读[安卓)由Coosle公司和开放手机联盟共同开发,它是基于Lmx内核的开源操作系统。Andtoid主要用于移动设备,如智能手机和平板计算机。2008年发布了第一部Andtoid智能手机,以后Android逐渐扩展到平板计算机、电视、…...
 
2024年,你是否还在迷茫?
2024年,你是否还在迷茫? 别担心!鸿蒙来了,这个未来技术的制高点,为你提供了答案! 诸多大厂疯抢、24年预计鸿蒙相关的岗位需求将达到百万级、就业均薪达到19K,全国高校开课…… 种种现象都在表…...
 
ART: Automatic multi-step reasoning and tool-use for large language models 导读
ART: Automatic multi-step reasoning and tool-use for large language models 本文介绍了一种名为“自动推理和工具使用(ART)”的新框架,用于解决大型语言模型(LLM)在处理复杂任务时需要手动编写程序的问题。该框架可…...
 
Github 2024-01-26 开源项目日报Top10
根据Github Trendings的统计,今日(2024-01-26统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目4Jupyter Notebook项目2HTML项目1Shell项目1Dockerfile项目1非开发语言项目1Go项目1Rust项目1 高级…...
 
免费的 UI 设计资源网站 Top 8
今日与大家分享8个优秀的免费 UI 设计资源网站。这些网站的资源包括免费设计材料站、设计工具、字体和其他网站,尤其是一些材料站。它们是免费下载的,材料的风格目前很流行,适合不同的项目。非常适合平面设计WEB/UI设计师收藏,接下…...
人机协同对人工智能治理的影响
人机协同对人工智能治理的影响是多方面的。 首先,人机协同可以提供更有效的人工智能监管和治理机制。人工智能系统通常需要大量的数据来训练和运行,而人类在监管和治理方面有独特的能力。通过人机协同,人们可以利用他们的主观意见和专业知识来…...
Form.List的使用,设置某个字段的值
1.Form.Item的name <Form.Itemname{[base_range, company_base_range_start]}dependencies{[[base_range, company_base_range_end]]}rules{[{ required: true, message: 请输入下限 },{validator: (_, value) >validateMoneyRule(value,base_range?.company_base_range…...
React16源码: React中的updateHostComponent的源码实现
updateHostComponent 1 )概述 在 completeWork 阶段的 HostComponent 处理,继续前文所述在更新的逻辑里面,调用了 updateHostComponent进行前后props对应的dom的attributes变化的对比情况这个方法也是根据不同环境来定义的,我们这…...
 
uniapp导入uView组件库
目录 准备工作 1. 新建一个项目 2. 导入uview组件库 3. 关于SCSS 配置步骤 1. 引入uView主JS库 2. 在引入uView的全局SCSS 3. 引入uView基础样式 4. 配置easycom组件模式 添加效果实验运行即可成功 准备工作 1. 新建一个项目 2. 导入uview组件库 在进行配置之前&#x…...
 
防御保护----防火墙的安全策略、NAT策略实验
实验拓扑: 实验要求: 1.生产区在工作时间(9:00-18:00)内可以访问DMZ区,仅可以访问http服务器; 2.办公区全天可以访问DMZ区,其中10.0.2.10可以访问FTP服务器和HTTP服务器…...
 
# 安徽锐锋科技IDMS系统简介
IDMS 由安徽锐锋科技独立开发 该系统负责和海算以及UE\UNITY的无缝衔接并具备远程数据库访问、高速数据库的自动创建及数据存储、支持MQTT等多种物联网接口,支持多种算法。主要完成由于物料、人员、生产、故障、不良异常、订单异常带来的生产损失,通过海…...
 
Notepad在文件中查找多行相同内容的文字
Notepad在文件中查找多行相同的内容 查找:打开 Notepad软件, Ctrl F 查找 。输入关键词, 点击【在当前文件中查找】。 复制:直接在下方的【搜索结果】复制。 Notepad提取含有特定字符串的行 详情见: https://blog…...
Python高超音速导弹
Python高超音速导弹的全自动化开发研发具有重要性的原因如下: 提高研发效率:全自动化开发可以通过自动化工具和流程,快速完成各种任务,包括代码编写、测试、集成和部署等。这样可以大大提高研发效率,缩短开发周期。 减…...
 
Java七大排序详解
排序 排序的概念 所谓排序 ,就是让一串记录,按照其中某些或者某个关键字的大小,递增或递减的排列起来的操作。 稳定性:就比如在待排序的序列中,存在多个具有相同关键字的记录 ,如果经过排序这些相同的关键…...
 
图像旋转角度计算并旋转
#!/usr/bin/python3 # -*- coding: utf-8 -*- import cv2 import numpy as np import timedef Rotate(img, angle0.0,fill0):"""旋转:param img:待旋转图像:param angle: 旋转角度:param fill:填充方式,默认0黑色填充:return: img: 旋转后…...
 
通过curl访问k8s集群获取证书或token的方式
K8S安全控制框架主要由下面3个阶段进行控制,每一个阶段都支持插件方式,通过API Server配置来启用插件。 1. Authentication(认证) 2. Authorization(授权) 3. Admission Control(准入控制&#…...
 
苍穹外卖-前端部分(持续更新中)
d 第二种:cmd中输入 vue ui进入图形化界面选择npm,vue2进行创建 先将创建的Vue框架导入Vsocde开发工具 然后ctrshiftp 输入npm 点击serve将项目启动 下这种写法跨域会报错: 解决方法:...
 
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
 
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
 
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
 
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
