Iterable#all 的行为是什么以及为什么 Kotlin Char::class.java != char.javaClass
What's the behavior of Iterable#all & Why did 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
})
}
列表包含 Char
或 String
但 all
函数在此表达式 returns false
,为什么 return false
?
谁能解释一下?
编辑
对于@JBNizet
正如@JB Nizet 已经告诉你如何分析问题。
根据 Mapped Types,Kotlin Char
将映射到 Java 类型决定其声明。
- 当声明为 不可空 类型时
Char
它是原始 Java 类型 char
.
- 当声明为 nullable 类型时
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
和其他包装器 classes 代表了 2 个角色。一个是 Java 原始类型 char
,另一个是 Java wrapper class java.lang.Character
。然而,Kotlin Char
是 statically 这意味着你不能在运行时改变它的类型。在 Kotlin 中,默认情况下 Char
应该映射到 char
。
如果你想每次都获取包装类型,你应该使用KClass.javaObjectType
代替,例如:
// v--- char
println(Char::class.java)
// v--- java.lang.Character
println(Char::class.javaObjectType)
Iterable#all
操作是一个短路操作,这意味着如果任何第一个元素不满足将立即return 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 class 时,如 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
}
我正在尝试使用 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
函数在此表达式 returns false
,为什么 return false
?
谁能解释一下?
编辑
对于@JBNizet
正如@JB Nizet 已经告诉你如何分析问题。
根据 Mapped Types,Kotlin Char
将映射到 Java 类型决定其声明。
- 当声明为 不可空 类型时
Char
它是原始 Java 类型char
. - 当声明为 nullable 类型时
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
和其他包装器 classes 代表了 2 个角色。一个是 Java 原始类型 char
,另一个是 Java wrapper class java.lang.Character
。然而,Kotlin Char
是 statically 这意味着你不能在运行时改变它的类型。在 Kotlin 中,默认情况下 Char
应该映射到 char
。
如果你想每次都获取包装类型,你应该使用KClass.javaObjectType
代替,例如:
// v--- char
println(Char::class.java)
// v--- java.lang.Character
println(Char::class.javaObjectType)
Iterable#all
操作是一个短路操作,这意味着如果任何第一个元素不满足将立即return 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 class 时,如 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
}