温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何测试java不可变类

发布时间:2026-09-11 07:48:16 来源:亿速云 阅读:94 作者:小樊 栏目:编程语言

在 Java 中,**不可变类(Immutable Class)**是指对象一旦创建,其状态(字段值)就不能被修改的类(如 StringInteger)。
“测试不可变类”通常有两层含义:

  1. 验证你写的类确实是不可变的(正确性测试)
  2. 在业务代码中对不可变类进行使用层面的测试

下面从测试思路 + 示例代码两方面说明。


一、如何验证一个类是不可变的(核心测试点)

1️⃣ 字段不能被修改

  • 所有字段应为 private final
  • 不提供 setter
  • 构造后字段值不可变

测试方式

@Test
public void testNoSetter() {
    Field[] fields = User.class.getDeclaredFields();
    for (Field f : fields) {
        assertFalse(Modifier.isPublic(f.getModifiers()));
        assertTrue(Modifier.isFinal(f.getModifiers()));
    }
}

2️⃣ 构造后对象状态不变

@Test
public void testImmutability() {
    User u1 = new User("Tom", 18);
    User u2 = u1;

    // 尝试通过任何方式修改
    // u1.setName("Jack"); // 编译错误,说明不可变

    assertEquals("Tom", u1.getName());
    assertEquals(18, u1.getAge());
}

3️⃣ 防御性拷贝(非常重要)

如果字段是可变对象(如 DateList),必须深拷贝。

public final class User {
    private final Date birthDate;

    public User(Date birthDate) {
        this.birthDate = new Date(birthDate.getTime()); // 防御拷贝
    }

    public Date getBirthDate() {
        return new Date(birthDate.getTime());
    }
}

测试防御性拷贝

@Test
public void testDefensiveCopy() {
    Date d = new Date();
    User u = new User(d);

    d.setTime(0); // 修改原对象
    assertNotEquals(0, u.getBirthDate().getTime());
}

4️⃣ 类本身不能被继承

public final class User {}

测试:

@Test
public void testClassIsFinal() {
    assertTrue(Modifier.isFinal(User.class.getModifiers()));
}

5️⃣ equals / hashCode / toString 稳定

不可变对象常用于 Map / Set,行为必须稳定。

@Test
public void testEqualsStable() {
    User u1 = new User("Tom", 18);
    User u2 = new User("Tom", 18);

    assertEquals(u1, u2);
    assertEquals(u1.hashCode(), u2.hashCode());
}

二、使用不可变类的测试建议

✅ 用 Builder 或静态工厂创建

User u = User.of("Tom", 18);

✅ 每次“修改”应返回新对象

User u2 = u.withAge(20);
assertNotSame(u, u2);

测试:

@Test
public void testWithMethod() {
    User u1 = new User("Tom", 18);
    User u2 = u1.withAge(20);

    assertEquals(18, u1.getAge());
    assertEquals(20, u2.getAge());
}

三、推荐测试工具

  • JUnit 5:基础单元测试
  • AssertJ:更语义化
assertThat(u1).isNotSameAs(u2);
  • ArchUnit(进阶):强制不可变规则

四、总结 checklist ✅

一个不可变类测试是否合格,看这几点:

  • [ ] 类是 final
  • [ ] 字段是 private final
  • [ ] 无 setter
  • [ ] 可变对象做了防御性拷贝
  • [ ] 修改操作返回新对象
  • [ ] equals/hashCode 稳定

如果你愿意,我可以帮你写一个完整的不可变类 + 对应测试示例

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI