You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Hamcrest的arrayWithSize在Kotlin中无法正常工作?

Kotlin中使用Hamcrest断言IntArray长度出现类型不匹配问题

我尝试用Hamcrest测试整数数组的长度,编写了如下Kotlin代码:

import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.collection.IsArrayWithSize.arrayWithSize
import org.hamcrest.core.IsEqual.equalTo
import org.hamcrest.core.Is.`is` as Is
…
     val parts = intArrayOf(1, 2, 3)
     assertThat(parts, arrayWithSize(3))
     assertThat(parts, Is(arrayWithSize(3)))
     assertThat(parts, Is(arrayWithSize(equalTo(3))))

据我理解这三种断言写法在Java中都能正常运行,但在Kotlin里却报出以下错误:

[ERROR] …/Decomposed_Test.kt:[287,14] Type mismatch: inferred type is IntArray but String! was expected
[ERROR] …/Decomposed_Test.kt:[287,21] Type mismatch: inferred type is Matcher<Array<(???..???)>!>! but Boolean was expected
[ERROR] …/Decomposed_Test.kt:[288,14] Type mismatch: inferred type is IntArray but String! was expected
[ERROR] …/Decomposed_Test.kt:[288,21] Type mismatch: inferred type is Matcher<(???..???)>! but Boolean was expected
[ERROR] …/Decomposed_Test.kt:[289,14] Type mismatch: inferred type is IntArray but String! was expected
[ERROR] …/Decomposed_Test.kt:[289,21] Type mismatch: inferred type is Matcher<(???..???)>! but Boolean was expected

错误提示明显不符合实际,我尝试为断言添加描述信息:

import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.collection.IsArrayWithSize.arrayWithSize
import org.hamcrest.core.IsEqual.equalTo
import org.hamcrest.core.Is.`is` as Is
…
     val parts = intArrayOf(1, 2, 3)
     assertThat(/* reason = */ "array has 3 elements", /* actual = */ parts, /* matcher = */ arrayWithSize(3))
     assertThat(/* reason = */ "array has 3 elements", /* actual = */ parts, /* matcher = */ Is(arrayWithSize(3)))
     assertThat(/* reason = */ "array has 3 elements", /* actual = */ parts, /* matcher = */ Is(arrayWithSize(equalTo(3))))

但仍然出现类型不匹配错误:

[ERROR] …/Decomposed_Test.kt:[287,91] Type mismatch: inferred type is IntArray! but Array<(out) TypeVariable(E)!>! was expected
[ERROR] …/Decomposed_Test.kt:[288,91] Type mismatch: inferred type is IntArray! but Array<(out) TypeVariable(E)!>? was expected
[ERROR] …/Decomposed_Test.kt:[288,91] Type mismatch: inferred type is IntArray! but Array<(out) TypeVariable(E)!>! was expected
[ERROR] …/Decomposed_Test.kt:[288,94] Type mismatch: inferred type is Matcher<Array<(out) (???..???)>!>! but Matcher<IntArray!>! was expected
[ERROR] …/Decomposed_Test.kt:[289,91] Type mismatch: inferred type is IntArray! but Array<(out) TypeVariable(E)!>? was expected
[ERROR] …/Decomposed_Test.kt:[289,91] Type mismatch: inferred type is IntArray! but Array<(out) TypeVariable(E)!>! was expected
[ERROR] …/Decomposed_Test.kt:[289,94] Type mismatch: inferred type is Matcher<Array<(out) (???..???)>!>! but Matcher<IntArray!>! was expected

问题原因

  1. 基本类型数组与对象数组的差异:Kotlin的IntArray对应Java的int[](基本类型数组),而Hamcrest的arrayWithSize匹配器是为Java的对象数组Array<E>(对应Kotlin的Array<Int>)设计的,二者类型不兼容,匹配器无法识别IntArray。
  2. 重载解析混乱:最初的错误提示(要求String/Boolean)是因为Kotlin的重载解析机制优先匹配了assertThat的其他重载方法(比如assertThat(String, Boolean)),而非我们需要的assertThat(T, Matcher<T>),导致错误提示偏离实际问题。

解决方案

方案1:转换为对象数组

将Kotlin的IntArray转换为Array<Int>(对应Java的Integer[]),即可直接使用原有Hamcrest匹配器:

val parts = intArrayOf(1, 2, 3).toTypedArray()
// 之后原有三种断言写法均可正常运行
assertThat(parts, arrayWithSize(3))
assertThat(parts, Is(arrayWithSize(3)))
assertThat(parts, Is(arrayWithSize(equalTo(3))))

方案2:自定义基本类型数组匹配器

如果不想转换数组类型,可以自定义针对IntArray的长度匹配器:

import org.hamcrest.BaseMatcher
import org.hamcrest.Description
import org.hamcrest.Matcher

fun intArrayWithSize(size: Int): Matcher<IntArray> = object : BaseMatcher<IntArray>() {
    override fun matches(item: Any?): Boolean {
        return item is IntArray && item.size == size
    }

    override fun describeTo(description: Description?) {
        description?.appendText("int array with size $size")
    }
}

// 扩展支持匹配器嵌套
fun intArrayWithSize(sizeMatcher: Matcher<Int>): Matcher<IntArray> = object : BaseMatcher<IntArray>() {
    override fun matches(item: Any?): Boolean {
        return item is IntArray && sizeMatcher.matches(item.size)
    }

    override fun describeTo(description: Description?) {
        description?.appendText("int array with size ")?.appendDescriptionOf(sizeMatcher)
    }
}

使用方式:

val parts = intArrayOf(1, 2, 3)
assertThat(parts, intArrayWithSize(3))
assertThat(parts, Is(intArrayWithSize(3)))
assertThat(parts, Is(intArrayWithSize(equalTo(3))))

内容的提问来源于stack exchange,提问作者Martin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 20:52:11