IntelliJ 误报「Condition is always false」警告的原因咨询
问题
我正在通过 exercism 的练习学习 Kotlin,当前正在完成三角形练习。我的部分解决方案如下:
class Triangle<out T : Number>(a: T, b: T, c: T) { init { require (a != 0 && b != 0 && c != 0) } }
在包含require()的代码行上,IntelliJ 给出如下警告:
Condition 'a != 0 && b != 0' is always false Condition 'a != 0 && b != 0 && c != 0' is always false
我编写了如下测试用例:
class TriangleTest { @Test fun `equilateral - all sides are equal`() { assertTrue(Triangle(2, 2, 2).isEquilateral) } @Test(expected = IllegalArgumentException::class) fun `equilateral - all zero sides is not a triangle`() { assertFalse(Triangle(0, 0, 0).isEquilateral) } }
这两个测试均已通过。若 IntelliJ 的警告正确,那么其中一个测试应该会失败。请问为何 IntelliJ 会给出这个错误的警告?
原因分析
这是IntelliJ静态代码分析对泛型T : Number的相等判断存在局限性导致的误报。
Kotlin中Number是所有数值类型的父类,a != 0本质是在比较Number类型对象与Int类型的0。由于Number是抽象类,不同数值子类(如Int、Double)的相等判断逻辑由各自实现决定,但静态分析工具无法精准推断所有子类的运行时行为,错误认定Number类型对象和0永远不相等,进而得出整个条件恒假的结论。
但实际运行时,当传入Int类型的2或0时,a != 0会调用Int类的相等判断逻辑,能正确识别2 != 0为真、0 != 0为假,所以你的测试可以正常通过。
要消除这个警告,可以将数值统一转换为同一种类型后再比较,比如:
require(a.toDouble() != 0.0 && b.toDouble() != 0.0 && c.toDouble() != 0.0)
这样既兼容所有Number子类的情况,也能让静态分析工具正确识别条件的有效性。
内容的提问来源于stack exchange,提问作者Code-Apprentice
相关产品推荐
相关产品推荐

