电子书 – Spring Cloud 指南 – NPI EA (分类=Spring Cloud)
announcement - icon

让我们开始使用 Spring Cloud 的微服务架构

>> 加入 Pro 并下载电子书

电子书 – Mockito – NPI EA (标签 = Mockito)
announcement - icon

模拟是单元测试的重要组成部分,Mockito 库使编写 清晰直观的单元测试 变得容易,用于您的 Java 代码。

通过我们的 Mockito 指南 开始模拟,并改进您的应用程序测试

下载电子书

电子书 – Java 并发 – NPI EA (分类=Java 并发)
announcement - icon

在应用程序中处理并发可能是一个棘手的过程,其中包含许多 潜在的陷阱。 扎实的掌握基本知识将有助于最大程度地减少这些问题。

通过我们的 Java 并发 指南开始了解多线程应用程序

>> 下载电子书

电子书 – 响应式 – NPI EA (分类=响应式)
announcement - icon

Spring 5 增加了对使用 Spring WebFlux 模块进行响应式编程的支持,此支持自那时起不断改进。 开始使用 Reactor 项目基础知识和 Spring Boot 中的响应式编程

>> 加入 Pro 并下载电子书

电子书 – Java Streams – NPI EA (分类=Java Streams)
announcement - icon

自从 Java 8 引入以来,Stream API 已成为 Java 开发的基础。 基本操作,例如迭代、过滤、映射元素序列,使用起来看似很简单。

但这些也可能被过度使用并陷入一些常见陷阱。

更好地了解 Stream 的工作方式 以及如何将其与其他语言功能结合使用,请查看我们关于 Java Streams 的指南

>> 加入 Pro 并下载电子书

电子书 – Jackson – NPI EA (分类=Jackson)
announcement - icon

用 Jackson 正确处理 JSON

下载电子书

电子书 – HTTP 客户端 – NPI EA (分类=Http 客户端)
announcement - icon

充分利用 Apache HTTP 客户端

下载电子书

电子书 – Maven – NPI EA (分类 = Maven)
announcement - icon

开始使用 Apache Maven

下载电子书

电子书 – 持久化 – NPI EA (分类=持久化)
announcement - icon

您在努力实现正确的持久化层 Spring 吗?

探索电子书

电子书 – RwS – NPI EA (分类=Spring MVC)
announcement - icon

使用 Spring 构建 REST API 吗?

下载电子书

课程 – LS – NPI EA (分类=Jackson)
announcement - icon

通过 Learn Spring 课程开始学习 Spring 和 Spring Boot

>> 学习 SPRING
课程 – RWSB – NPI EA (分类=REST)
announcement - icon

通过构建一个完整的 REST API,深入了解 Spring Boot 3 和 Spring 6,使用该框架

>> 全新的“REST With Spring Boot”

课程 – LSS – NPI EA (分类=Spring Security)
announcement - icon

是的,Spring Security 可能很复杂,从核心内的更高级功能到框架中深入的 OAuth 支持。

我将安全材料构建为 两个完整的课程 - 核心和 OAuth,以针对这些更复杂的场景进行实践。 我们探索何时以及如何使用每个功能,并 在后台项目中对其进行编码

您可以在这里探索该课程

>> 学习 Spring Security

课程 – LSD – NPI EA (标签=Spring Data JPA)
announcement - icon

Spring Data JPA 是处理 JPA 复杂性的绝佳方式,它具有 Spring Boot 的强大简洁性

通过引导式参考课程开始使用 Spring Data JPA

>> 查看课程

合作伙伴 – Moderne – NPI EA (类别=Spring Boot)
announcement - icon

使用 OpenRewrite 安全且自动地重构 Java 代码。

手动重构大型代码库既缓慢、有风险,又容易拖延。OpenRewrite 应运而生。这个用于大规模、自动化代码转换的开源框架可以帮助团队安全、一致地进行现代化改造。

每个月,OpenRewrite 的创建者和维护者 Moderne 都会举办现场、实践培训课程——一个面向初学者,一个面向经验丰富的用户。您将了解配方的运作方式、如何将其应用于项目,以及如何自信地进行代码现代化改造。

参加下一次课程,带来您的问题,并学习如何自动化通常会占用您 sprint 时间的工作。

合作伙伴 – LambdaTest – NPI EA (类别=测试)
announcement - icon

回归测试是发布流程中的重要步骤,以确保新代码不会破坏现有功能。随着代码库的不断发展,我们希望频繁运行这些测试,以便尽早发现任何问题。

确保这些测试以自动化的方式频繁运行的最佳方法当然是将其包含在 CI/CD 管道中。 这样,每次向仓库提交代码时,回归测试将自动执行。

在本教程中,我们将学习如何使用 Selenium 创建回归测试,然后使用 GitHub Actions 将它们包含在我们的管道中,在 LambdaTest 云网格上运行

>> 如何使用 GitHub Actions 运行 Selenium 回归测试

课程 – LJB – NPI EA (类别 = Core Java)
announcement - icon

通过编码方式构建 Java 的坚实、实用的基础

>> 学习 Java 基础

1. 概述

Apache Commons Lang 3 库 是一个流行且功能齐全的实用类包,旨在扩展 Java API 的功能

该库的功能非常丰富,涵盖字符串、数组和数字操作、反射和并发,以及对成对和三元组等多个有序数据结构的实现(通常称为 元组)。

在本教程中,我们将深入研究该库中最有用的实用类

2. Maven 依赖

像往常一样,要开始使用 Apache Commons Lang 3,我们首先需要添加 Maven 依赖

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.14.0</version>
</dependency>

3. StringUtils

我们将在此介绍中介绍的第一个实用类是 StringUtils.

顾名思义,StringUtils 允许我们执行一系列空安全字符串操作,这些操作补充/扩展了java.lang.String开箱即用的操作

让我们开始展示一组用于对给定字符串执行各种检查的实用方法,例如确定字符串是否为空白、为空、小写、大写、字母数字等

@Test
public void whenCalledisBlank_thenCorrect() {
    assertThat(StringUtils.isBlank(" ")).isTrue();
}
    
@Test
public void whenCalledisEmpty_thenCorrect() {
    assertThat(StringUtils.isEmpty("")).isTrue();
}
    
@Test
public void whenCalledisAllLowerCase_thenCorrect() {
    assertThat(StringUtils.isAllLowerCase("abd")).isTrue();
}
    
@Test
public void whenCalledisAllUpperCase_thenCorrect() {
    assertThat(StringUtils.isAllUpperCase("ABC")).isTrue();
}
    
@Test
public void whenCalledisMixedCase_thenCorrect() {
    assertThat(StringUtils.isMixedCase("abC")).isTrue();
}
    
@Test
public void whenCalledisAlpha_thenCorrect() {
    assertThat(StringUtils.isAlpha("abc")).isTrue();
}
    
@Test
public void whenCalledisAlphanumeric_thenCorrect() {
    assertThat(StringUtils.isAlphanumeric("abc123")).isTrue();
}

当然,StringUtils 类实现了许多其他方法,为了简单起见,我们在此省略了它们。

对于检查或对给定字符串应用某种转换算法的其他一些附加方法,请 查看本教程

上面介绍的方法非常简单明了,因此单元测试应该不言自明。

4. ArrayUtils

ArrayUtils 类实现了一批实用方法,允许我们以各种不同的方式处理和检查数组.

让我们从toString() 的两个重载实现开始,它返回给定数组的字符串表示形式,并在数组为 null 时返回一个特定的字符串

@Test
public void whenCalledtoString_thenCorrect() {
    String[] array = {"a", "b", "c"};
    assertThat(ArrayUtils.toString(array))
      .isEqualTo("{a,b,c}");
}

@Test
public void whenCalledtoStringIfArrayisNull_thenCorrect() {
    assertThat(ArrayUtils.toString(null, "Array is null"))
      .isEqualTo("Array is null");
}

接下来,我们有hashCode()toMap() 方法。

前者为数组生成自定义 hashCode 实现,后者将数组转换为Map

@Test
public void whenCalledhashCode_thenCorrect() {
    String[] array = {"a", "b", "c"};
    assertThat(ArrayUtils.hashCode(array))
      .isEqualTo(997619);
}
    
@Test
public void whenCalledtoMap_thenCorrect() {
    String[][] array = {{"1", "one", }, {"2", "two", }, {"3", "three"}};
    Map map = new HashMap();
    map.put("1", "one");
    map.put("2", "two");
    map.put("3", "three");
    assertThat(ArrayUtils.toMap(array))
      .isEqualTo(map);
}

最后,让我们看一下isSameLength() indexOf() 方法。

前者用于检查两个数组是否具有相同的长度,后者用于获取给定元素的索引

@Test
public void whenCalledisSameLength_thenCorrect() {
    int[] array1 = {1, 2, 3};
    int[] array2 = {1, 2, 3};
    assertThat(ArrayUtils.isSameLength(array1, array2))
      .isTrue();
}

@Test
public void whenCalledIndexOf_thenCorrect() {
    int[] array = {1, 2, 3};
    assertThat(ArrayUtils.indexOf(array, 1, 0))
      .isEqualTo(0);
}

StringUtils 类一样,ArrayUtils 实现更多其他方法。您可以在 本教程 中了解更多信息。

在这种情况下,我们仅展示了最具代表性的方法。

5. NumberUtils

Apache Commons Lang 3 的另一个关键组件是 NumberUtils 类。

如预期的那样,该类提供了大量的实用方法,旨在处理和操作数值类型

让我们看一下compare() 的重载实现,它比较不同的原始类型(例如intlong)的相等性

@Test
public void whenCalledcompareWithIntegers_thenCorrect() {
    assertThat(NumberUtils.compare(1, 1))
      .isEqualTo(0);
}
    
@Test
public void whenCalledcompareWithLongs_thenCorrect() {
    assertThat(NumberUtils.compare(1L, 1L))
      .isEqualTo(0);
}

此外,还存在对byteshort类型操作的compare()实现,其工作方式与上述示例非常相似。

接下来在本综述中是createNumber()isDigit()方法。

第一个允许我们创建一个string的数字表示,而第二个检查一个string是否仅由数字组成

@Test
public void whenCalledcreateNumber_thenCorrect() {
    assertThat(NumberUtils.createNumber("123456"))
      .isEqualTo(123456);
}
    
@Test
public void whenCalledisDigits_thenCorrect() {
    assertThat(NumberUtils.isDigits("123456")).isTrue();
}

在寻找给定数组的最小值和最大值时,NumberUtils类通过min()max()方法的重载实现为此类操作提供了强大的支持

@Test
public void whenCalledmaxwithIntegerArray_thenCorrect() {
    int[] array = {1, 2, 3, 4, 5, 6};
    assertThat(NumberUtils.max(array))
      .isEqualTo(6);
}
    
@Test
public void whenCalledminwithIntegerArray_thenCorrect() {
    int[] array = {1, 2, 3, 4, 5, 6};
    assertThat(NumberUtils.min(array)).isEqualTo(1);
}
    
@Test
public void whenCalledminwithByteArray_thenCorrect() {
    byte[] array = {1, 2, 3, 4, 5, 6};
    assertThat(NumberUtils.min(array))
      .isEqualTo((byte) 1);
}

6. Fraction

使用笔和纸处理分数一切都很好。 但是,在编写代码时,我们是否需要经历这个过程的复杂性? 实际上不是。

Fraction 类使加、减和乘分数变得轻而易举:

@Test
public void whenCalledgetFraction_thenCorrect() {
    assertThat(Fraction.getFraction(5, 6)).isInstanceOf(Fraction.class);
}
    
@Test
public void givenTwoFractionInstances_whenCalledadd_thenCorrect() {
    Fraction fraction1 = Fraction.getFraction(1, 4);
    Fraction fraction2 = Fraction.getFraction(3, 4);
    assertThat(fraction1.add(fraction2).toString()).isEqualTo("1/1");
}
    
@Test
public void givenTwoFractionInstances_whenCalledsubstract_thenCorrect() {
    Fraction fraction1 = Fraction.getFraction(3, 4);
    Fraction fraction2 = Fraction.getFraction(1, 4);
    assertThat(fraction1.subtract(fraction2).toString()).isEqualTo("1/2");
}
    
@Test
public void givenTwoFractionInstances_whenCalledmultiply_thenCorrect() {
    Fraction fraction1 = Fraction.getFraction(3, 4);
    Fraction fraction2 = Fraction.getFraction(1, 4);
    assertThat(fraction1.multiplyBy(fraction2).toString()).isEqualTo("3/16");
}

虽然分数运算肯定不是我们在日常开发工作中需要处理的最常见任务,但Fraction 类为以直接的方式执行这些操作提供了有价值的支持。

7. SystemUtils

有时,我们需要获取有关底层 Java 平台或操作系统的不同属性和变量的一些动态信息。

Apache Commons Lang 3 提供了SystemUtils,可以以一种无痛的方式完成此操作.

例如,考虑getJavaHome()getUserHome()isJavaVersionAtLeast() 方法

@Test
public void whenCalledgetJavaHome_thenCorrect() {
    assertThat(SystemUtils.getJavaHome())
      .isEqualTo(new File("path/to/java/jdk"));
}

@Test
public void whenCalledgetUserHome_thenCorrect() {
    assertThat(SystemUtils.getUserHome())
      .isEqualTo(new File("path/to/user/home"));
}

@Test
public void whenCalledisJavaVersionAtLeast_thenCorrect() {
    assertThat(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_RECENT)).isTrue();
}

SystemUtils 类实现了一些其他的实用方法。 我们省略了它们以保持示例的简短。

8. 延迟初始化和 Builder 类

Apache Commons Lang 3 最吸引人的方面之一是实现了某些众所周知的设计模式,包括延迟初始化建造者模式.

例如,假设我们创建了一个昂贵的User类(为简洁起见未显示),并希望将其实例化推迟到真正需要时。

在这种情况下,我们需要做的就是扩展参数化LazyInitializer抽象类并覆盖其initialize()方法

public class UserInitializer extends LazyInitializer<User> {

    @Override
    protected User initialize() {
        return new User("John", "[email protected]");
    }
}

现在,如果我们需要在需要时获取我们的高成本User对象,我们只需调用UserInitializerget()方法

@Test 
public void whenCalledget_thenCorrect() 
  throws ConcurrentException { 
    UserInitializer userInitializer = new UserInitializer(); 
    assertThat(userInitializer.get()).isInstanceOf(User.class); 
}

get() 方法是实例字段的双重检查习语(线程安全)的实现,如Joshua Bloch 的“Effective Java”第 71 条

private volatile User instance;
 
User get() { 
    if (instance == null) { 
        synchronized(this) { 
            if (instance == null) 
                instance = new User("John", "[email protected]"); 
            }
        } 
    } 
    return instance; 
}

此外,Apache Commons Lang 3 实现了 HashCodeBuilder 类,它允许我们通过向 builder 提供不同的参数(基于典型的流利 API)来生成hashCode() 实现

@Test
public void whenCalledtoHashCode_thenCorrect() {
    int hashcode = new HashCodeBuilder(17, 37)
      .append("John")
      .append("[email protected]")
      .toHashCode();
    assertThat(hashcode).isEqualTo(1269178828);
}

我们可以对 BasicThreadFactory 类进行类似的操作,并创建具有命名模式和优先级的守护线程

@Test
public void whenCalledBuilder_thenCorrect() {
    BasicThreadFactory factory = new BasicThreadFactory.Builder()
      .namingPattern("workerthread-%d")
      .daemon(true)
      .priority(Thread.MAX_PRIORITY)
      .build();
    assertThat(factory).isInstanceOf(BasicThreadFactory.class);
}

9. ConstructorUtils

反射在 Apache Commons Lang 3 中是一等公民。

该库包含几个反射类,允许我们以反射方式访问和操作类字段和方法。

例如,假设我们实现了一个简单的 User 领域类

public class User {

    private String name;
    private String email;
    
    // standard constructors / getters / setters / toString
}

假设它的参数化构造函数是 public,我们可以使用 ConstructorUtils 类轻松访问它

@Test
public void whenCalledgetAccessibleConstructor_thenCorrect() {
    assertThat(ConstructorUtils
      .getAccessibleConstructor(User.class, String.class, String.class))
      .isInstanceOf(Constructor.class);
}

除了通过构造函数进行标准的类实例化外,我们可以通过调用 invokeConstructor()invokeExactConstructor() 方法以反射方式创建 User 实例

@Test
public void whenCalledinvokeConstructor_thenCorrect() 
  throws Exception {
      assertThat(ConstructorUtils.invokeConstructor(User.class, "name", "email"))
        .isInstanceOf(User.class);
}

@Test
public void whenCalledinvokeExactConstructor_thenCorrect() 
  throws Exception {
      String[] args = {"name", "email"};
      Class[] parameterTypes= {String.class, String.class};
      assertThat(ConstructorUtils.invokeExactConstructor(User.class, args, parameterTypes))
        .isInstanceOf(User.class);
}

10. FieldUtils

同样,我们可以使用 FieldUtils 类的这些方法以反射方式读取/写入类字段

假设我们想要获取 User 类的某个字段,或者最终获取该类从超类继承的某个字段。

在这种情况下,我们可以调用 getField() 方法

@Test
public void whenCalledgetField_thenCorrect() {
    assertThat(FieldUtils.getField(User.class, "name", true).getName())
      .isEqualTo("name");
}

或者,如果我们想要使用更严格的反射范围,并且只获取 User 类中声明的字段,而不从超类继承,我们将只使用 getDeclaredField() 方法

@Test
public void whenCalledgetDeclaredFieldForceAccess_thenCorrect() {
    assertThat(FieldUtils.getDeclaredField(User.class, "name", true).getName())
      .isEqualTo("name");
}

此外,我们可以使用 getAllFields() 方法获取反射类的字段数量,并使用 writeField()writeDeclaredField() 方法将值写入声明的字段或层次结构中定义的字段

@Test
public void whenCalledgetAllFields_thenCorrect() {
    assertThat(FieldUtils.getAllFields(User.class).length)
      .isEqualTo(2);  
}

@Test
public void whenCalledwriteField_thenCorrect() 
  throws IllegalAccessException {
    FieldUtils.writeField(user, "name", "Julie", true);
    assertThat(FieldUtils.readField(user, "name", true))
      .isEqualTo("Julie");     
}
    
@Test
public void givenFieldUtilsClass_whenCalledwriteDeclaredField_thenCorrect() throws IllegalAccessException {
    FieldUtils.writeDeclaredField(user, "name", "Julie", true);
    assertThat(FieldUtils.readField(user, "name", true))
      .isEqualTo("Julie");    
}

11. MethodUtils

同样,我们可以使用 MethodUtils 类对类方法进行反射。

在这种情况下,User 类的 getName() 方法的可见性是 public。因此,我们可以使用 getAccessibleMethod() 方法访问它

@Test
public void whenCalledgetAccessibleMethod_thenCorrect() {
    assertThat(MethodUtils.getAccessibleMethod(User.class, "getName"))
      .isInstanceOf(Method.class);
}

在以反射方式调用方法时,我们可以使用 invokeExactMethod()invokeMethod() 方法

@Test
public 
  void whenCalledinvokeExactMethod_thenCorrect() 
  throws Exception {
    assertThat(MethodUtils.invokeExactMethod(new User("John", "[email protected]"), "getName"))
     .isEqualTo("John");
}

@Test
public void whenCalledinvokeMethod_thenCorrect() 
  throws Exception {
    User user = new User("John", "[email protected]");
    Object method = MethodUtils.invokeMethod(user, true, "setName", "John");
    assertThat(user.getName()).isEqualTo("John");
}

12. MutableObject

虽然不变性是良好面向对象软件的关键特性,我们应该在每种可能的情况下都将其作为默认设置,但不幸的是,有时我们需要处理可变对象。

此外,创建可变类需要大量的样板代码,这可以通过大多数 IDE 通过自动生成的 setter 生成。

为此,Apache Commons Lang 3 提供了 MutableObject 类,一个用于创建可变对象的简单包装类,无需繁琐的操作

@BeforeClass
public static void setUpMutableObject() {
    mutableObject = new MutableObject("Initial value");
}
    
@Test
public void whenCalledgetValue_thenCorrect() {
    assertThat(mutableObject.getValue()).isInstanceOf(String.class);
}
    
@Test
public void whenCalledsetValue_thenCorrect() {
    mutableObject.setValue("Another value");
    assertThat(mutableObject.getValue()).isEqualTo("Another value");
}
    
@Test
public void whenCalledtoString_thenCorrect() {
    assertThat(mutableObject.toString()).isEqualTo("Another value");    
}

当然,这只是如何使用 MutableObject 类的一个例子。

作为经验法则,我们应该始终努力创建不可变类,或者在最坏的情况下,只提供所需的变异级别

13. MutablePair

有趣的是,Apache Commons Lang 3 以配对和三元组的形式为元组提供了强大的支持。

所以,假设我们需要创建一个可变的有序元素对。

在这种情况下,我们将使用 MutablePair

private static MutablePair<String, String> mutablePair;

@BeforeClass
public static void setUpMutablePairInstance() {
    mutablePair = new MutablePair<>("leftElement", "rightElement");
}
    
@Test
public void whenCalledgetLeft_thenCorrect() {
    assertThat(mutablePair.getLeft()).isEqualTo("leftElement");
}
    
@Test
public void whenCalledgetRight_thenCorrect() {
    assertThat(mutablePair.getRight()).isEqualTo("rightElement");
}
    
@Test
public void whenCalledsetLeft_thenCorrect() {
    mutablePair.setLeft("newLeftElement");
    assertThat(mutablePair.getLeft()).isEqualTo("newLeftElement");
}

这里值得强调的最相关的细节是该类的简洁 API。

它允许我们通过标准的 setter/getter 设置和访问配对封装的左右对象。

14. ImmutablePair

毫不奇怪,MutablePair 类也有一个不可变对应的实现,称为 ImmutablePair

private static ImmutablePair<String, String> immutablePair = new ImmutablePair<>("leftElement", "rightElement");
    
@Test
public void whenCalledgetLeft_thenCorrect() {
    assertThat(immutablePair.getLeft()).isEqualTo("leftElement");
}
    
@Test
public void whenCalledgetRight_thenCorrect() {
    assertThat(immutablePair.getRight()).isEqualTo("rightElement");
}
    
@Test
public void whenCalledof_thenCorrect() {
    assertThat(ImmutablePair.of("leftElement", "rightElement"))
      .isInstanceOf(ImmutablePair.class);
}
    
@Test(expected = UnsupportedOperationException.class)
public void whenCalledSetValue_thenThrowUnsupportedOperationException() {
    immutablePair.setValue("newValue");
}

正如我们可能期望的那样,任何尝试通过setValue()方法更改配对的内部状态的行为都将导致抛出UnsupportedOperationException异常。

15. Triple

我们将要查看的最后一个工具类是Triple

由于该类是抽象的,我们可以使用of()静态工厂方法来创建Triple实例

@BeforeClass
public static void setUpTripleInstance() {
    triple = Triple.of("leftElement", "middleElement", "rightElement");
}
    
@Test
public void whenCalledgetLeft_thenCorrect() {
    assertThat(triple.getLeft()).isEqualTo("leftElement");
}
    
@Test
public void whenCalledgetMiddle_thenCorrect() {
    assertThat(triple.getMiddle()).isEqualTo("middleElement");
}
    
@Test
public void whenCalledgetRight_thenCorrect() {
    assertThat(triple.getRight()).isEqualTo("rightElement");
}

通过MutableTripleImmutableTriple类,也存在可变和不可变的 triple 的具体实现。

我们可以通过参数化构造函数创建它们的实例,而不是使用静态工厂方法。

在这种情况下,我们将跳过它们,因为它们的 API 非常类似于MutablePairImmutablePair类的 API。

16. 结论

在本教程中,我们深入了解了Apache Commons Lang 3提供的一些最有用的现成的工具.

该库实现了许多其他值得一看的工具类这里,我们只是根据一个相当主观的标准展示了最有用的工具类。

有关完整的库API,请查看官方Javadoc

支持本文的代码可在 GitHub 上获取。 一旦你Baeldung Pro 会员 身份登录,就开始学习并在项目上进行编码。
Baeldung Pro – NPI EA (类别 = Baeldung)
announcement - icon

Baeldung Pro 具有完全无广告以及最终具有深色模式,提供干净的学习体验

>> 探索干净的 Baeldung

一旦早期采用者的席位全部用完,价格将上涨并保持在每年 33 美元。

电子书 – HTTP 客户端 – NPI EA (类别=HTTP 客户端)
announcement - icon

Apache HTTP Client 是一个非常强大的库,适用于简单和高级用例,在测试 HTTP 端点时尤其适用。 查看我们的指南,涵盖基本请求和响应处理,以及安全性、Cookie、超时等。

>> 下载电子书

电子书 – Java 并发 – NPI EA (分类=Java 并发)
announcement - icon

在应用程序中处理并发可能是一个棘手的过程,其中包含许多 潜在的陷阱。 扎实的掌握基本知识将有助于最大程度地减少这些问题。

通过我们的 Java 并发 指南开始了解多线程应用程序

>> 下载电子书

电子书 – Java Streams – NPI EA (分类=Java Streams)
announcement - icon

自从 Java 8 引入以来,Stream API 已成为 Java 开发的基础。 基本操作,例如迭代、过滤、映射元素序列,使用起来看似很简单。

但这些也可能被过度使用并陷入一些常见陷阱。

更好地了解 Stream 的工作方式 以及如何将其与其他语言功能结合使用,请查看我们关于 Java Streams 的指南

>> 加入 Pro 并下载电子书

电子书 – 持久化 – NPI EA (分类=持久化)
announcement - icon

您在努力实现正确的持久化层 Spring 吗?

探索电子书

课程 – LS – NPI EA (类别=REST)

announcement - icon

从 Spring Boot 开始,通过 Learn Spring 课程了解核心 Spring。

>> 查看课程

合作伙伴 – Moderne – NPI EA (标签=重构)
announcement - icon

现代 Java 团队行动迅速——但代码库并不总是跟上。 框架会发生变化,依赖关系会漂移,技术债务会累积,直到它开始拖慢交付速度。 OpenRewrite 就是为此而构建的:一个开源重构引擎,可在保持开发人员意图不变的同时自动化重复的代码更改。

由 Moderne 的 OpenRewrite 创建者和维护者领导的每月培训系列,将介绍实际的迁移和现代化模式。 无论您是重构配方的新手,还是准备编写自己的配方,您都将学习以安全且可扩展的方式进行重构的实用方法。

如果您曾经希望重构感觉像编写代码一样自然——并且一样快速——这是一个很好的起点

电子书 Jackson – NPI EA – 3 (类别 = Jackson)
© .