我在kotlin尝试一个例子,如:
fun test(){
val harfler = listOf("a","b",'c','d')
println(harfler.all {
it.javaClass == String::class.java || it.javaClass == Char::class.java
})
}
列表包含Char
或String
,但此表达式中的 all
函数返回false
,为什么返回false
?
有人可以解释一下吗?
答案 0 :(得分:3)
正如@JB Nizet已经告诉过你如何分析这个问题。
根据Mapped Types,Kotlin Char
将映射到Java Type决定其声明。
Char
时,它是原始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 })
但我想说使用和声明之间存在差异。
例如,参数类型it
是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
应映射到char
。
IF 您希望每次都获得包装类型,您应该使用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
}
检查Kotlin类时,如Char
和其他人。你应该使用Kotlin type checking机制而不是传统的比较方法,它可以帮助你避免这种混乱。例如:
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
因此,您的代码可以替换为type checking,如下所示:
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
}