sd4324530 2017-09-21 03:00 采纳率: 0%
浏览 40

Kotlin和Java混合使用的时候很郁闷

Kotlin自身对定义的变量默认为不可空,在纯Kotlin开发的时候确实很舒服,少写很多代码,但是和Java混合开发的时候,最简单的例子,我在Kotlin项目中依赖第三方的java库,调用里面的方法,kotlin貌似默认全部认为方法的返回值都是可空的,导致拿到返回值后继续使用,全部都要判断非空,就算你可以明确知道不可能为空,也要在代码上加上!!来保证接下来可以直接使用。但是在链式调用的时候,非常蛋疼,每一步都要!!,极其难看,对于这个问题,有没有什么好的解决方法呢?

  • 写回答

1条回答 默认 最新

  • 禅与计算机程序设计艺术 人工智能领域优质创作者 2017-09-21 06:52
    关注

    您好!

    Kotlin和Java混合使用确实是体验不佳的。没有写纯纯的Kotlin那么爽的。

    Kotlin 在设计之初就考虑了与 Java 的互操作性。我们可以从 Kotlin 中自然地调用现存的 Java 代码。

    但是,如果,我们在Kotlin中调用Java代码中的丑陋的特性(比如说,null),这确实是不得已的事情。

    一下内容摘自《Kotlin极简教程》 10.1.5 小节:

    10.1.5 调用来自Java中的null
    我们知道Java 中的任何引用都可能是null,这样我们在使用 Kotlin调用来自 Java 的对象的时候就有可能会出现空安全的问题。

    平台类型
    Java 声明的类型在 Kotlin 中会被特别对待并称为平台类型(platform types )。对这种类型的空检查会放宽,因此它们的安全保证与在 Java 中相同。
    请看以下示例:
    @RunWith(JUnit4::class)
    class CallingJavaNullSafe {
    @Test fun testCallingJavaNullSafe() {
    val product = Product()
    // product.name = null
    product.category = "金融财务类"
    product.gmtCreated = Date()
    product.gmtModified = Date()
    println(JSONUtils.toJsonString(product))

        val name = product.name
        println("product name is ${name}")
    
        val eqName = name == "账务系统"
        println(eqName)
    
        name.substring(1)
    }
    

    }
    上面的代码可以正确编译通过。Kotlin编译器对来自Java的空值name(平台类型)放宽了空检查name.substring(1)。但是这样的空指针异常仍然会在运行时抛出来。
    运行上面的代码,我们可以看到输出:
    {"category":"金融财务类","gmtCreated":1500050426817,"gmtModified":1500050426817}
    product name is null
    false

    null cannot be cast to non-null type java.lang.String
    kotlin.TypeCastException: null cannot be cast to non-null type java.lang.String
    at com.easy.kotlin.CallingJavaNullSafe.testCallingJavaNullSafe(CallingJavaNullSafe.kt:27)
    我们没有设置name的值,在Java它就是null。我们在Kotlin代码中使用了这个name进行计算,我们可以看出:
    val eqName = name == "账务系统"
    println(eqName)
    可以正确输出false。这表明Kotlin的判断字符串是否相等已经对null的情况作了判断处理,这样的代码如果在Java中调用 name.equals("账务系统") 就该抛空指针异常了。
    但是当我们直接使用name这个值来调用name.substring(1)的时候,Kotlin编译器不会检查这个空异常,但是运行时还是要报错的:null cannot be cast to non-null type java.lang.String。
    如果我们不想看到这样的异常,而是当name是null的时候,安静的输出null,直接使用Kotlin中的空安全的调用 .? :
    name?.substring(1)
    这样,运行的时候不会抛出异常,直接安静的返回null。
    平台类型助记符

    平台类型不能在程序中显式表述,因此在语言中没有相应语法。 然而,编译器和 IDE 有时需要(在错误信息中、参数信息中等)显示他们,所以我们用一个助记符来表示他们:
     T! : 表示 T 或者 T?
     (Mutable) Collection! : 表示 “可以可变或不可变、可空或不可空的 T 的 Java 集合”
     Array<(out) T>! : 表示可空或者不可空的 T(或 T 的子类型)的 Java 数组

    评论

报告相同问题?

悬赏问题

  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效