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

标签 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 
    })
}

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

谁能解释一下吗?

编辑 对于@JBNizet enter image description here

最佳答案

正如@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 })
    

但是我想说,用法声明之间是有区别的。 例如参数类型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 wrapperjava.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/

相关文章:

ruby - 在编译过程中何时/何地发生类型检查

Java - 保存对象(集合)的更好模型

hibernate - Kotlin Hibernate JPA Lazy提取无法通过 Controller 工作

android - 在方向变化时维护虚拟键盘的更简洁方法

android - 无法下载 kotlin-reflect.jar (org.jetbrains.kotlin :kotlin-reflect:1. 3.0):没有可用于离线模式的缓存版本

c++ - 如何测试迭代器值是否具有整数类型?

c# - Xunit.Assert.Collection 中的问题 - C#

每个调用方法和 addAll 的 Java 8 lambda

java - 排序时,在数组列表的最后位置放置一个空对象或空对象

haskell - 在 Haskell 中为命令式语言编写解释器