什么是Iterable的行为#all&为什么Kotlin Char :: class.java!= char.javaClass

我正在尝试kotlin中的一个例子,如:

fun test(){ val harfler = listOf("a","b",'c','d') println(harfler.all { it.javaClass == String::class.java || it.javaClass == Char::class.java }) } 

List包含Char或者String但是这个表达式中的all函数all返回false ,为什么返回false

有人可以解释吗?

编辑 @JBNizet 在这里输入图像描述

正如@JB Nizet已经告诉过你如何分析这个问题。

根据映射类型 ,Kotlin Char将被映射到Java类型决定其声明。

  • 当声明为不可为空的类型时,它是一个原始的Java类型char
  • 当声明为可空类型的Char? 它是一个Java包装类型的Character
  • 当声明为一个类型参数 List<Char>它是一个Java包装类型Character

     val it = 'a' // v--- it should be `Any` val array: Array<Any> = arrayOf('a') // v--- char println(it.javaClass) // v--- print [java.lang.Character] println(array.map { it.javaClass }) 

但是我想说的是,在用法声明之间还有一个不同之处。 例如,参数类型是java.lang.Character ,但是它的javaClasschar

 fun typeOf(it: Char?) = it?.javaClass fun test() { // v--- java.lang.Character println(::typeOf.javaMethod!!.parameterTypes[0]) // v--- but it return `char` rather than `java.lang.Character` println(typeOf('a')) } 

下面的例子显示了不同之处,这就是为什么我在前面的例子中将数组类型声明为Array<Any>而不是Array<Char>

 // v--- uses `java.lang.Character` instead val array: Array<Char> = arrayOf('a') // v--- java.lang.Character println(array.javaClass.componentType) // v--- [char] println(array.map { it.javaClass }) 

奇怪的行为为什么发生在Koltin?

这是因为Kotlin Char和其他包装类代表2个角色。 一个是Java 原始类型的 char ,另一个是Java 包装java.lang.Character 。 但是,Kotlin Char静态的 ,这意味着你不能在运行时改变它的类型。 并且Char应该被映射到Kotlin默认的char

如果你想每次获得包装类型,你应该使用KClass.javaObjectType来代替,例如:

 // v--- char println(Char::class.java) // v--- java.lang.Character println(Char::class.javaObjectType) 

Iterable#all操作是短路操作,这意味着如果任何第一个元素不满足将立即返回false

 inline fun <T> Iterable<T>.all(predicate: (T) -> Boolean): Boolean { // return `false` immediately the condition didn't satisfied // v for (element in this) if (!predicate(element)) return false return true } 

当检查像Char等Kotlin类。 您应该使用Kotlin 类型检查机制而不是传统的比较方法,它可以帮助您避免这种混淆。 例如:

 val anything: Array<Any> = arrayOf('a') val chars: Array<Char> = arrayOf('a') println(chars.all { it is Char }) // print true println(anything.all { it is Char }) // print true 

所以你的代码可以用下面的类型检查代替:

 fun test() { val harfler = listOf("a", "b", 'c', 'd') // v---------------v--- use type checking here println(harfler.all { it is String || it is Char }) // print true }