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

时间:2017-07-30 08:26:22

标签: collections kotlin typechecking

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

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

列表包含CharString,但此表达式中的 all 函数返回false,为什么返回false

有人可以解释一下吗?

修改 为@JBNizet enter image description here

1 个答案:

答案 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 })
    

但我想说使用声明之间存在差异。 例如,参数类型itjava.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应映射到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
}