什么是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
,但是它的javaClass
是char
。
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 }