我正在尝试 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
函数返回 false
,为什么返回false
?
谁能解释一下吗?
最佳答案
正如@JB Nizet 已经告诉你如何分析问题。
根据Mapped Types , Kotlin Char
将被映射到 Java 类型,由其声明决定。
- 当声明为不可空类型时
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 wrapper 类 java.lang.Character
。然而,Kotlin Char
是静态,这意味着您无法在运行时更改其类型。和一个 Char
应映射到 char
Kotlin 中默认情况下。
如果您想每次都获取包装类型,则应该使用 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
}
关于collections - Iterable#all 的行为是什么?为什么 Kotlin Char::class.java != char.javaClass,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45397859/