介绍

JUnit 5 是一个用于 Java 编程语言的单元测试框架,它是 JUnit 框架的第五个版本,与 JUnit 4 相比,JUnit 5 提供了许多改进和新特性,包括更好的扩展性、灵活性和对现代 Java 特性的支持。

JUnit 5 由三个主要的子模块组成:

  • JUnit Platform:这是 JUnit 5 的基础,它提供了一个测试引擎的接口,可以运行多种测试框架。JUnit Platform 不仅支持 JUnit 5,还支持 JUnit 4 和其他测试框架(比如 TestNG)。它也定义了如何启动测试、报告结果等基础设施。
  • JUnit Jupiter:这是 JUnit 5 的核心模块,也是 JUnit 5 中最常用的部分,包含了用于编写和运行测试的 API 和注解。
  • JUnit Vintage:这个模块为 JUnit 4 和早期版本的测试提供兼容性支持,它允许在同一个项目中同时运行 JUnit 4 和 JUnit 5 的测试。


常用注解 Annotations

@Test

在 JUnit 5 中,@Test 用于标记一个普通的测试方法,表示该方法应该被测试框架识别并执行。

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;public class MyTest {@Testvoid testAddition() {int result = 1 + 1;assertEquals(2, result);}
}

在这个例子中,testAddition 方法被 @Test 注解标记为一个测试方法。当运行这个测试类时,JUnit 会自动执行 testAddition 方法并验证 assertEquals(2, result) 是否成立。如果条件不满足,测试将失败。


生命周期

在 JUnit 5 中,@BeforeAll@AfterAll@BeforeEach @AfterEach 等生命周期注解可以在测试方法的前后执行一些必要的初始化或清理工作,它们的作用域是所在测试类。

@BeforeAll

  • 作用:标记的方法会在所有测试方法执行之前执行一次,适用于需要在所有测试方法运行之前进行一次性初始化的场景。

  • 要求:被 @BeforeAll 注解的方法必须是 static,因为它是由 JUnit 框架在类加载时直接调用的,并不依赖于类的实例。

@AfterAll

  • 作用:标记的方法会在所有测试方法执行完毕之后执行一次,适用于需要在所有测试方法完成之后进行一些清理操作的场景。

  • 要求:和 @BeforeAll 一样,@AfterAll 标记的方法必须是 static,因为它也是由 JUnit 在类的生命周期结束时调用的。

@BeforeEach

  • 作用:标记的方法会在每个测试方法执行之前执行一次,适用于每个测试方法需要单独的初始化工作,例如每个测试方法都要创建一个新的数据库连接。

@AfterEach

  • 作用:标记的方法会在每个测试方法执行之后执行一次,适用于需要在每个测试方法后进行清理的操作,例如关闭数据库连接、清理测试环境。

示例:

import org.junit.jupiter.api.*;class LifecycleTest {// 在所有测试方法执行前执行一次@BeforeAllstatic void beforeAll() {System.out.println("Before All - 执行一次");}// 在所有测试方法执行后执行一次@AfterAllstatic void afterAll() {System.out.println("After All - 执行一次");}// 在每个测试方法执行前执行@BeforeEachvoid beforeEach() {System.out.println("Before Each - 每个测试方法前执行");}// 在每个测试方法执行后执行@AfterEachvoid afterEach() {System.out.println("After Each - 每个测试方法后执行");}@Testvoid test1() {System.out.println("Test 1 - 执行测试 1");}@Testvoid test2() {System.out.println("Test 2 - 执行测试 2");}
}

输出:

Before All - 执行一次
Before Each - 每个测试方法前执行
Test 1 - 执行测试 1
After Each - 每个测试方法后执行
Before Each - 每个测试方法前执行
Test 2 - 执行测试 2
After Each - 每个测试方法后执行
After All - 执行一次

@ParameterizedTest

在传统的单元测试中,每个测试方法通常都是针对特定的输入值进行测试。使用 @ParameterizedTest 可以为同一个测试方法提供不同的输入数据,从而更全面地验证代码的正确性。

如何使用 @ParameterizedTest

@ParameterizedTest 需要与 参数源(Source)一起使用,参数源提供了不同的输入数据集合。JUnit 5 提供了几种常用的参数源,包括 @ValueSource、@CsvSource、@MethodSource、@EnumSource 等。

1. 使用 @ValueSource 传递单个参数

@ValueSource 是最常见的参数源之一,它允许为测试方法传递单一类型的多个值。

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.ParameterizedTest;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.provider.ValueSource;public class ParameterizedTestExample {@ParameterizedTest@ValueSource(ints = {1, 2, 3, 4, 5})  // 提供参数源:一个整数数组void testWithValues(int number) {Assertions.assertTrue(number > 0);  // 对每个输入参数执行相同的断言}
}

在这个示例中,@ParameterizedTest 与 @ValueSource 结合,提供了多个整数值。每次执行 testWithValues 方法时,JUnit 5 会用不同的整数值执行测试,验证它们是否大于 0。

@ValueSource 支持的类型包括但不限于以下:

  • ints
  • floats
  • booleans
  • strings
  • classes

值得注意的是,如果需要传递对象型的参数,可以传递 json 字符串,然后反序列化成对象。

2. 使用 @CsvSource 传递多个参数

@CsvSource 允许以CSV 格式(逗号分隔的值)传递多个参数,这对需要多个输入的测试非常有用。

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.ParameterizedTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.provider.CsvSource;public class ParameterizedTestCsvSource {@ParameterizedTest@CsvSource({"1, 2, 3","4, 5, 9",  // 两个整数和预期结果"10, 20, 30"})void testSum(int a, int b, int expectedSum) {Assertions.assertEquals(expectedSum, a + b);  // 验证 a + b 是否等于预期结果}
}

在这个例子中,@CsvSource 提供了三组数据,每一组数据有两个整数值和一个期望的结果。JUnit 5 会为每一组数据执行一次 testSum 方法。

3. 使用 @MethodSource 从方法中提供参数

@MethodSource 允许从一个静态方法中提供参数。这个方法必须返回一个包含多个测试数据的 Stream、Iterable 或 Object[]。

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.ParameterizedTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.provider.MethodSource;import java.util.stream.Stream;public class ParameterizedTestMethodSource {static Stream<String> stringProvider() {return Stream.of("apple", "banana", "cherry");}@ParameterizedTest@MethodSource("stringProvider")void testWithMethodSource(String fruit) {Assertions.assertNotNull(fruit);  // 确保输入的每个字符串都是非空的}
}

在这个示例中,stringProvider() 方法返回了一个 Stream,这个 Stream 会被用作 testWithMethodSource 的参数源。每次运行时,JUnit 5 会用 apple、banana 和 cherry 分别执行 testWithMethodSource 方法。

4. 使用 @EnumSource 来测试枚举值

@EnumSource 是一个特别有用的注解,用于枚举类型的参数化测试。它允许为测试方法传递一个枚举类的所有值,或者指定枚举值的子集。

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.ParameterizedTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.provider.EnumSource;public class ParameterizedTestEnumSource {enum Fruit {APPLE, BANANA, CHERRY}@ParameterizedTest@EnumSource(Fruit.class)  // 传入枚举类的所有值void testWithEnumSource(Fruit fruit) {Assertions.assertNotNull(fruit);  // 确保传入的枚举值非空}
}

在这个示例中,@EnumSource(Fruit.class) 会让 JUnit 5 将 Fruit 枚举中的每个值(APPLE、BANANA、CHERRY)传递给 testWithEnumSource 方法。


@Tag

@Tag 注解的用途

  • 测试分类:可以为测试方法或测试类指定一个或多个标签,进而根据标签来组织和筛选测试。
  • 条件化执行:可以根据不同的标签在测试执行时选择性地执行某些测试,而跳过其他测试,例如“快速测试”或“性能测试”。

在测试类或方法上使用 @Tag

@Tag 可以应用于 测试类测试方法 上,指定一个或多个标签。

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Tag;@Tag("smoke")
public class MultiTagTest {@Test@Tag("fast")@Tag("smoke")void fastSmokeTest() {// 这个测试同时是 "fast" 和 "smoke" 类型的测试}
}

使用构建工具(Maven、Gradle)筛选标签

在构建工具(如 Maven 或 Gradle)中,可以根据标签来筛选哪些测试需要执行。

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.0.0-M5</version><configuration><includes><include>@fast</include> <!-- 只运行标签为 fast 的测试 --></includes></configuration>
</plugin>

@DisplayName

在 JUnit 5 中,@DisplayName 注解用来为测试类、或测试方法指定一个 自定义的显示名称。这个显示名称会在测试报告中展示,以使得测试结果更具可读性和易于理解。

import org.junit.jupiter.api.*;@DisplayName("测试生命周期方法的注解")
class DisplayNameTest {@BeforeEachvoid setUp() {System.out.println("BeforeEach - 每个测试前执行");}@Test@DisplayName("测试方法 1:加法测试")void testAddition() {int result = 2 + 3;Assertions.assertEquals(5, result);}@Test@DisplayName("测试方法 2:减法测试")void testSubtraction() {int result = 5 - 3;Assertions.assertEquals(2, result);}
}

@Disabled

@Disabled 用于 禁用 某个测试类或测试方法,使其在测试运行时 不被执行

import org.junit.jupiter.api.*;class DisabledTest {@Test@Disabled("此测试暂时禁用")void testNotRun() {System.out.println("这个测试方法不会被执行");}@Testvoid testRun() {System.out.println("这个测试方法会被执行");}
}

@ExtendWith

@ExtendWith 是 JUnit5 中用于扩展测试功能的注解,它允许在测试类或测试方法中添加扩展(Extension),扩展可以是 JUnit5 提供的标准扩展,也可以是自定义的扩展。@ExtendWith 注解的主要目的是使 JUnit5 更加灵活,能够集成第三方库、提供特定的生命周期管理或自定义测试行为。

添加Mockito扩展示例:

@ExtendWith(MockitoExtension.class)


断言 Assertions

org.junit.Assert.assertTrue 是 JUnit 4 中用于检查条件是否为 true 的断言方法。

在 JUnit 5 中,这个方法被移动到了 org.junit.jupiter.api.Assertions 类中,并且推荐使用 import static 导入,方便直接调用断言方法。

Assertions 类包含的常见断言方法:

  • assertEquals(expected, actual) — 判断预期值与实际值是否相等。
  • assertNotEquals(expected, actual) — 判断预期值与实际值是否不相等。
  • assertTrue(condition) — 判断条件是否为 true。
  • assertFalse(condition) — 判断条件是否为 false。
  • assertNull(object) — 判断对象是否为 null。
  • assertNotNull(object) — 判断对象是否不为 null。
  • assertSame(expected, actual) — 判断两个对象是否是同一个实例。
  • assertNotSame(expected, actual) — 判断两个对象是否不是同一个实例。
  • assertThrows(expectedType, executable) — 判断代码块是否抛出预期的异常。
  • assertAll(Executable... assertions) — 执行多个断言并报告所有失败的情况。
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;public class CalculatorTest {@Testvoid testAddition() {int sum = 2 + 3;assertEquals(5, sum, "2 + 3 should equal 5");}@Testvoid testIsEmpty() {String str = "";assertTrue(str.isEmpty(), "String should be empty");}@Testvoid testNotNull() {String name = "JUnit";assertNotNull(name, "Name should not be null");}
}


假设Assumptions

在 JUnit 中,Assumptions 是一种用来在测试运行之前检查前提条件(假设条件)的机制。如果假设条件不成立,测试会被跳过,而不是失败

1. Assume.assumeTrue(boolean condition)

Assume.assumeTrue() 会检查给定的条件是否为 true。如果条件为 false,则跳过当前测试。

2. Assume.assumeFalse(boolean condition)

Assume.assumeFalse() 与 assumeTrue() 类似,但它会检查条件是否为 false。如果条件为 true,则跳过当前测试。

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assumptions;
import static org.junit.jupiter.api.Assertions.*;public class OSBasedTest {@Testvoid testOnlyOnLinux() {// 假设条件:当前操作系统必须是 LinuxAssumptions.assumeTrue(System.getProperty("os.name").contains("Linux"), "Test can only be run on Linux");// 这里放置 Linux 上才有意义的测试逻辑String expected = "LinuxTest";String actual = getLinuxSpecificFeature();assertEquals(expected, actual);}private String getLinuxSpecificFeature() {// 模拟在 Linux 上获取某个特定的功能return "LinuxTest";}
}


异常处理

在 JUnit 5 中,异常处理是一个重要的功能,用于验证代码是否按预期抛出异常。JUnit 5 提供了几种方法来检查代码是否会抛出预期的异常,并且可以对异常进行更详细的控制和验证。

assertThrows 方法

在 JUnit 5 中,最常用的异常验证方法是 assertThrows()。它用于验证代码是否抛出了预期类型的异常。

import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;class CalculatorTest {@Testvoid testDivideByZero() {Calculator calculator = new Calculator();assertThrows(ArithmeticException.class, () -> calculator.divide(1, 0),"Expected ArithmeticException when dividing by zero");}
}

assertDoesNotThrow 方法

与 assertThrows() 相对的是 assertDoesNotThrow(),它用于验证代码块是否 不抛出任何异常

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import org.junit.jupiter.api.Test;class CalculatorTest {@Testvoid testAdd() {Calculator calculator = new Calculator();assertDoesNotThrow(() -> calculator.add(2, 3),"Addition should not throw any exception");}
}

assertThrows 检查异常消息

在 JUnit 5 中,assertThrows() 除了可以检查异常类型,还可以检查异常的消息。要检查异常的消息,我们可以获取到抛出的异常对象,并验证其 getMessage() 方法。

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;class CalculatorTest {@Testvoid testDivideByZeroWithMessage() {Calculator calculator = new Calculator();ArithmeticException thrown = assertThrows(ArithmeticException.class, () -> calculator.divide(1, 0));assertEquals("Cannot divide by zero", thrown.getMessage(), "The exception message should match the expected message");}
}

throws 异常传播

JUnit 5 允许在测试方法上声明 throws,使得测试方法可以抛出异常并且让 JUnit 处理。这对那些会抛出受检查异常(例如 IOException)的测试方法非常有用。

import org.junit.jupiter.api.Test;
import java.io.IOException;class FileTest {@Testvoid testFileRead() throws IOException {// 这里的代码可能会抛出 IOExceptionthrow new IOException("File not found");}
}


条件执行 Conditional

在 JUnit 5 中,条件执行(Conditional Execution)允许根据不同的条件来决定是否执行某个测试或生命周期方法。条件执行可以在不同的环境、操作系统、配置或其他因素下动态地跳过或启用某些测试方法。

JUnit 5 提供了多个注解和机制来支持条件执行,主要包括:

  • @EnabledIf 系列注解
  • @DisabledIf 系列注解
  • @EnabledIfSystemProperty 和 @DisabledIfSystemProperty
  • @EnabledIfEnvironmentVariable 和 @DisabledIfEnvironmentVariable
  • @EnabledIfModule 和 @DisabledIfModule
  • @EnabledIfAny 和 @DisabledIfAny
  • @EnabledIfAll 和 @DisabledIfAll

示例: 

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.api.condition.DisabledIf;class ConditionalTest {@Test@EnabledIf(expression = "#{systemProperties['os.name'].contains('Linux')}", reason = "Runs only on Linux")void testOnlyOnLinux() {System.out.println("This test runs only on Linux");}@Test@DisabledIf(expression = "#{systemProperties['os.name'].contains('Windows')}", reason = "Does not run on Windows")void testNotOnWindows() {System.out.println("This test does not run on Windows");}
}


测试执行顺序 (Test Execution Order)

在 JUnit 5 中,测试类和测试方法的执行顺序默认是确定性的,这意味着虽然每次运行测试套件时,测试类和测试方法会按照固定的顺序执行,但我们不应该预测或依赖于这一顺序来编写测试。


JUnit4 vs JUnit5 以及注意事项

1. 架构上的差异

  • JUnit4:JUnit4 使用的是一个单一的类库,所有的测试逻辑和扩展都集成在一起。
  • JUnit5:JUnit5 引入了一个更为模块化的架构,分为三个主要的子模块:
    • JUnit Platform:负责启动测试框架,提供支持运行测试的基础设施。
    • JUnit Jupiter:包含 JUnit5 的新特性和扩展机制(如新的注解、条件化测试等)。
    • JUnit Vintage:支持运行 JUnit4 和早期版本的测试。

2. @Test

  • JUnit4 的 @Test 注解位于 org.junit.Test 包中。
  • JUnit5 的 @Test 注解位于 org.junit.jupiter.api.Test 包中。JUnit5 将所有新的测试框架和 API 放在了 org.junit.jupiter 中。

3. @Before / @After 与 @BeforeEach / @AfterEach

  • JUnit4:使用 @Before 和 @After 注解在每个测试方法执行前后执行初始化和清理操作。
  • JUnit5:使用 @BeforeEach @AfterEach 注解,功能和 @Before / @After 相同。

4. @BeforeClass / @AfterClass 与 @BeforeAll / @AfterAll

  • JUnit4:使用 @BeforeClass 和 @AfterClass 注解执行类级别的初始化和清理操作,这些方法必须是 static 的。
  • JUnit5:使用 @BeforeAll @AfterAll 注解,功能类似 @BeforeClass 和 @AfterClass,也需要方法是 static 的。

5. @RunWith 与 @ExtendWith

  • JUnit4:使用 @RunWith 注解来指定测试运行器,如 @RunWith(MockitoJUnitRunner.class)。
  • JUnit5:使用 @ExtendWith 注解来指定扩展,JUnit5 使用了更灵活的扩展机制。

6. @Ignore 与 @Disabled

  • JUnit4:使用 @Ignore 注解来跳过某个测试方法或测试类。
  • JUnit5:使用 @Disabled 注解来禁用某个测试方法或测试类。

7. @Test(expected = Exception.class) 与 assertThrows

  • JUnit4:使用 @Test(expected = Exception.class) 来测试方法是否抛出指定的异常。
  • JUnit5:使用 assertThrows() 方法。

8. @ClassRule 和 @Rule 与 @ExtendWith

  • JUnit4:使用 @ClassRule 和 @Rule 来创建类级别和方法级别的规则。
  • JUnit5:JUnit5 更加灵活,使用 @ExtendWith 注解来扩展规则,可以实现类似的功能。

9. 断言 (Assertions)

  • JUnit4:断言方法位于 org.junit.Assert 类中。
  • JUnit5:断言方法移至 org.junit.jupiter.api.Assertions 类,并增加了更丰富的断言方法。

不推荐使用 assert 关键字 来做单元测试的断言,因为 Java 中的 assert 语句并不是为单元测试设计的,而是用于程序运行时的调试和开发阶段。

10. 集成 Mockito

  • MockitoAnnotations.initMocks(testClass) 是在 JUnit 4 中使用 Mockito 进行依赖注入的常见方式。
  • @ExtendWith(MockitoExtension.class) 是 JUnit 5 引入的功能,用于更简洁地集成 Mockito。


参考

JUnit 5 User Guide

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/86954.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/86954.shtml
英文地址,请注明出处:http://en.pswp.cn/web/86954.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源 java android app 开发(十三)绘图定义控件、摇杆控件的制作

文章的目的为了记录使用java 进行android app 开发学习的经历。本职为嵌入式软件开发&#xff0c;公司安排开发app&#xff0c;临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 java an…

Python 库 包 sentence-transformers

sentence-transformers 是一个非常流行的 Python 库&#xff0c;专门用于将文本&#xff08;句子、段落、文档&#xff09;转换为高质量的语义向量&#xff08;嵌入&#xff09;。它基于 Transformer 架构&#xff08;如 BERT、RoBERTa、DistilBERT 等&#xff09; 的预训练模型…

《聚类算法》入门--大白话篇:像整理房间一样给数据分类

一、什么是聚类算法&#xff1f; 想象一下你的衣柜里堆满了衣服&#xff0c;但你不想一件件整理。聚类算法就像一个聪明的助手&#xff0c;它能自动帮你把衣服分成几堆&#xff1a;T恤放一堆、裤子放一堆、外套放一堆。它通过观察衣服的颜色、大小、款式这些特征&#xff0c;把…

AutoGen(五) Human-in-the-Loop(人类在环)实战与进阶:多智能体协作与Web交互全流程(附代码)

AutoGen Human-in-the-Loop&#xff08;人类在环&#xff09;实战与进阶&#xff1a;多智能体协作与Web交互全流程&#xff08;附代码&#xff09; 引言&#xff1a;AI自动化的极限与人类参与的价值 在大模型&#xff08;LLM&#xff09;驱动的AI应用开发中&#xff0c;完全自…

并查集 Union-Find

目录 引言 简单介绍 浅浅总结 算法图解 初始化 根节点查找 集合合并 连通性检查 例题 大概思路 完整代码&#xff1a; 引言 一个小小的并查集让我们在ccpc卡了那么久(还有unordered_map,如果不是忘了map自动排序这么一回事也不至于试那么多发)&#xff0c;至今仍然心有…

书籍在行列都排好序的矩阵中找数(8)0626

题目&#xff1a; 给定一个有N*M的整型矩阵matrix和一个整数K&#xff0c;matrix的每一行和每一列都是排好序的。实现一个函数&#xff0c;判断K是否在matrix中。 0 1 2 5 2 3 4 7 4 4 4 8 5 …

深度学习04 卷积神经网络CNN

卷积神经网络与人工神经网络关系与区别 概念 卷积神经网络&#xff08;Convolutional Neural Network, CNN&#xff09;是人工神经网络&#xff08;Artificial Neural Network, ANN&#xff09;的一种特殊形式&#xff0c;两者在核心思想和基础结构上存在关联&#xff0c;但在…

vue基础之组件通信(VUE3)

文章目录 前言一、父子组件通信1.父组件向子组件通信2.子组件向父组件通信3.ref父组件直接操作子组件通信。 二、跨代通信1. 跨层级通信2.事件总线通信 总结 前言 vue3的组件通信和vue2相比在语法上会有些差距&#xff0c;且vue3有的通信方式也在功能上比vue2更加完善&#xf…

【RidgeUI AI+系列】中文重复统计器

中文重复统计器 文字重复统计是一个使用文本处理工具&#xff0c; 输入文本内容并指定最小词长度后&#xff0c; 就能自动高亮显示重复的词。 本教程将会借助AI实现这个应用的开发 页面脚本编写 该工具的基础流程较为清晰&#xff1a;用户输入一段文字后&#xff0c;调用提取…

代码随想录|图论|05岛屿数量(深搜DFS)

leetcode:99. 岛屿数量 题目 题目描述&#xff1a; 给定一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的矩阵&#xff0c;你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成&#xff0c;并且四周都是水域。你可以假设矩阵外均…

数据结构-第二节-堆栈与队列

一、概念&#xff1a; 堆栈与队列也是线性表&#xff0c;但是&#xff1a; 堆栈&#xff1a;只能在一个端进行插入删除&#xff0c;此端称为栈顶。&#xff08;特点&#xff1a;后来居上&#xff09; 队列&#xff1a;在一端进行插入&#xff08;队尾&#xff09;&#xff0…

HarmonyNext动画大全02-显式动画

HarmonyOS NEXT显式动画详解 1. 核心接口 显式动画通过animateTo接口实现&#xff0c;主要特点包括&#xff1a; 触发方式&#xff1a;需主动调用接口触发动画 参数配置 &#xff1a; animateTo({duration: 1000, // 动画时长(ms)curve: Curve.Ease, // 动画曲线delay: 200…

芯谷科技--高压降压型 DC-DC 转换器D7005

在当今电子设备日益复杂且对电源性能要求极高的背景下&#xff0c;一款高效、稳定的电源管理芯片至关重要。 D7005凭借其卓越的性能和广泛的应用适配性&#xff0c;成为众多工程师在设计电源方案时的优选。 产品简介 D7005 是一款高效、高压降压型 DC-DC 转换器&#xff0c;具…

MySQL的GTID详解

GTID&#xff08;Global Transaction Identifier&#xff0c;全局事务标识符&#xff09;是MySQL 5.6及以上版本引入的重要特性&#xff0c;用于在主从复制环境中唯一标识每个事务&#xff0c;简化复制管理、故障转移和数据一致性维护。以下从多维度详细介绍GTID&#xff1a; …

专题:2025中国游戏科技发展研究报告|附130+份报告PDF、原数据表汇总下载

原文链接&#xff1a;https://tecdat.cn/?p42756 本报告汇总解读基于艾瑞咨询《2025中国游戏科技发展白皮书》、伽马数据《2025年1-3月中国游戏产业季度报告》、嘉世咨询《2025中国单机游戏市场现状报告》等多份行业研报数据。当《黑神话&#xff1a;悟空》以虚幻引擎5复刻东…

【数据挖掘】数据挖掘综合案例—银行精准营销

要求&#xff1a; 1、根据相关的信息预测通过电话推销&#xff0c;用户是否会在银行进行存款 2、数据bank.csv&#xff0c;约4520条数据&#xff0c;17个属性值 提示&#xff1a; 17个属性&#xff0c;分别是年龄&#xff0c;工作类型&#xff0c;婚姻状况&#xff0c;受教育…

postgresql查看锁的sql语句

发现一个查看postgresql锁比较好的sql语句&#xff0c;参考链接地址如下 链接地址 查看锁等待sql witht_wait as(select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,a.granted,a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,a.trans…

JSON 格式详解

JSON 格式详解 随着互联网的发展和各种 Web 应用程序的普及&#xff0c;数据交换已经成为了我们日常开发中的重要环节。而在各种数据交换格式中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;作为一种轻量级的数据交换格式&#xff0c;以其简洁、易于阅…

原型设计Axure RP网盘资源下载与安装教程共享

对于初学者来说&#xff0c;我们熟悉一下其定义&#xff1a;‌Axure RP是一款常用的快速原型设计工具‌&#xff0c;主要用于创建应用软件或Web网站的线框图、流程图、原型和规格说明文档&#xff0c;广泛应用于产品经理、UI/UX设计师等专业领域。‌‌ 主要用户群体&#xff1…

iframe嵌套 redirect中转页面 route跳转

需求是项目A要使用iframe内嵌项目B的页面&#xff0c; 由于需要嵌套的页面很多&#xff0c;每个页面路径和参数又各不相同&#xff0c; 所以我们在项目B里做了一个中转页面&#xff0c;这样就能自己掌控项目A传递过来的东西了&#xff1b; routes.js 增加一个菜单&#xff1a;…