前言

Kotlin 1.4 正式版在好早以前就已经发布了。关于那些“看得见”的新特性,比如SAM转换、参数列表末尾的可选逗号什么的,已经有无数文章介绍过了。所以本文打算介绍一些可能是鲜为人知的、Kotlin 官方团队偷偷塞进 1.4 的新特性。

不过单独讲这些东西会显得文章太过单薄,于是我打算把其他相似的东西拉一起凑凑字数。

本文使用的 Kotlin 版本为 Kotlin 1.4。

本文要讲的东西

看题目就知道了,Kotlin 里自动类型转换(automatic type conversion)。这里讲的不是 「把一个 String 转成 Any,再转成 String」 这种和子类型有关的东西,当然也不是 Smart Cast,而是两个不相容的类型之间的转换,比如说 Int 转成 Long,如下文所示。

数值转换

一般地,在 Kotlin 里我们不能像 Java 一样直接把一个 Int 类型的东西赋值给 Long 类型的变量,因为它们之间并不具有子类型关系。像下面这样会得到一个编译错误:

val int: Int = 555
val long: Long = int // 编译错误!
println(long)

你需要调用标准库提供给你的那些 toXXX 函数把数值转换成其他类型的数值。

val int: Int = 555
val long: Long = int.toLong() // OK
println(long)

Kotlin 官方团队曾经表示过不喜欢隐式(implicit)的东西,关于数值的隐式类型转换也包括在内。这就导致了使用 Kotlin 在进行一些关于数值方面的操作时,有时候会写出一些看起来无比蛋疼的代码。

Bennyhuo:就是有时候写点儿计算比较多的代码,满篇的 toFloat toDouble。

不一般地,我们可以使用 @Suppress 来搞事:

val int: Int = 233
@Suppress("TYPE_MISMATCH")
val long: Long = int
println(long) // 233

这个代码是可以跑起来的,而且你真的可以从字节码里看到那个把 Int 转成 Long 的指令 I2L。

不过我不确定 Kotlin 的其他 target 是否能这样用,我也不保证这样写完全不会出问题。(这里是关于 @Suppress 的免责声明,请读者自行脑补)

SAM Conversion

SAM 转换也是一种自动类型转换。它把一个 lambda 表达式(具有函数类型)转成某个具体的接口类型。

fun interface ISome {
 fun some()
}

fun useSome(some: ISome) {}

useSome { println("some") }

在我的另一篇文章里有更详细的介绍。

如果读者不同意这个说法,可以选择跳过本小节内容。

Coercion to Unit

我们都知道 Kotlin 的 lambda 表达式是使用里面最后一个表达式的值来作为 lambda 的返回值的。比如这样:

val block = { "yeah" }

block 的类型是 () -> String。

然后我们来看看这样的情况:

fun test(block: () -> Unit) {
 println(block())
}

test { "yeah" } // 输出 Unit

相信很多人都熟悉这样的写法。

在某些初学者的眼里这看起来像是把一个 () -> String 类型的 lambda 传给了需要 () -> Unit 类型的函数。

这就是 coercion to unit,一个很久以前就存在的特性,可以理解为编译器自动帮你在 lambda 表达式的最后加了一行 Unit,把本来应该是() -> String 类型的 lambda 变成了 () -> Unit 类型。

在 Kotlin 1.4 版本,这个特性得到了进化,你甚至可以这样写:

fun test(block: () -> Unit) {
 println(block())
}

fun some(): String {
 return "str"
}

// 需要 Kotlin 1.4 版本
test(::some) // 输出 Unit

编译器帮你把 () -> String 类型的函数引用转成了 () -> Unit。

Unit Conversion

警告:这是一项未完成的特性!

添加编译器参数 -XXLanguage: UnitConversion,你就开启了一个 Kotlin 官方团队偷偷塞进 1.4 版本的未完成的新特性。

这个特性允许你写出这样的代码:

fun test(block: () -> Unit) {
 println(block())
}

fun some(block: () -> String) {
 test(block) // 这里是重点
 // 如果你不加那个编译器参数,会报错
}

fun main() {
 some { "str" }
 // 理论上会输出 Unit
}

在函数 some 里把一个 () -> String 传给了 test 函数,可以看出来这个特性其实和 coercion to unit 是差不多的。

理论上这样的代码运行时会输出 Unit,但是目前由于该特性的代码生成没写好,得不到预期的结果。

另外,在开启了这个特性后,() -> String 并不会成为 () -> Unit 的子类型,它们依然是两个不相容的类型。

Suspend Conversion

警告:这是一项未完成的特性!

这是本文要介绍的第二个 Kt 官方团队偷偷塞进 1.4 版本的未完成的新特性。

比如说我们有这样的一个函数:

fun test(f: suspend () -> Unit) {
 // do something with f
}

我们可以这样调用它:

test { println("hi") } 

但是这样不行:

val f = { println("hi") }
test(f) // 编译错误

编译器会告诉你类型不匹配,f 是 () -> Unit 类型,test 函数需要 suspend () -> Unit 类型的参数。

当你添加了编译器参数 -XXLanguage: SuspendConversion,就可以让上面的代码通过编译。

也就是说这个特性可以帮你把普通函数类型的值转成 suspend 函数类型。

当然由于这是未完成的功能,即使可以通过编译,但是跑起来还是会炸。

这个特性或许会在 Kotlin 1.5 版本完工,但请不要抱有期待。

结尾

我并不想讨论「为什么要加这种奇怪的特性」之类的话题。

不可否认的是,在有限的程序员生涯中,这些新特性可能一次也用不上。上面提到的问题也都有相应的 workaround,不需要新特性也可以写出等价的代码,就是没有那么优雅罢了(

到此这篇关于关于Kotlin自动类型转换的文章就介绍到这了,更多相关Kotlin自动类型转换内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

关于Kotlin的自动类型转换详解的更多相关文章

  1. Kotlin难点解析:extension和this指针

    扩展是Kotlin语言中使用非常简单的一个特性。关于这个问题,其实我之前的一篇文章[[Kotlin]LambdaandExtension](https://www.jianshu.com/p/d7a...中有提到过。为了解决这个问题,官方提出了两个新的概念:dispatchreceiver和extensionreceiver。extensionreceiver:中文翻译为扩展接收者。为了简化,这里我们将dispatchreceiver简称为DR,将extensionreceiver简称为ER。如果你习惯了

  2. android – Kotlin类NoClassDefFoundError崩溃

    我有一个使用以下库的现有Android项目:>Autovalue>Dagger2>RxJava>Retrolambda我正在尝试添加Kotlin支持,以便我可以将项目慢慢迁移到Kotlin.这就是我所做的.>添加了Kotlin依赖.>将其中一个类转换为Kt类并转移到src/main/kotlin/..包中.>在源集中添加了kotlin.sourceSets{main.java.srcDirs=’s

  3. android – Kotlin和Dagger2

    我正在尝试将Kotlin添加到我的项目中,但在启用Kotlin之后我无法构建,因为Dagger2类不再生成.我尝试了第二个项目,我有同样的问题.这些是我为启用Kotlin所做的改变:项目build.gradle:Appbuild.gradle:错误发生在这里:其中不再定义DaggerObjectGraph.任何帮助将不胜感激.解决方法只需删除

  4. android – 在Kotlin中不能使用argb color int值吗?

    当我想在Kotlin中为TextView的textColor设置动画时:发生此错误:似乎在Kotlin中不能将值0xFF8363FF和0xFFC953BE强制转换为Int,但是,它在Java中是正常的:有任何想法吗?提前致谢.解决方法0xFF8363FF是Long,而不是Int.你必须明确地将它们转换为Int:关键是0xFFC953BE的数值是4291384254,因此它应该存储在Long变量中.但这里的高位是符号位,表示负数:-3583042,可以存储在Int中.这就是两种语言之间的区别.在Kotlin

  5. 什么是我可以使用Kotlin的最早的Android API级别?

    我认为这个问题很清楚但是我能在Kotlin上定位的最早API级别是什么?解决方法实际上,任何API级别.这是因为Kotlin被编译为JVM6平台的字节码,所有AndroidAPI级别都支持该字节码.因此,除非您在Kotlin代码中使用任何较新的AndroidAPI,否则它不需要任何特定的API级别.

  6. android – Kotlin数据类和可空类型

    我是Kotlin的新手,我不知道为什么编译器会抱怨这段代码:编译器抱怨测试?.data.length,它说我应该这样做:test?.length.但是数据变量是String,而不是String?,所以我不明白为什么我要把它?当我想检查长度.解决方法表达式test?.data部分可以为空:它是test.data或null.因此,获取其长度并不是零安全的,而是应该再次使用safecalloperator:test?.length.可空性通过整个调用链传播:你必须将这些链写成?.)).e),因为,如果其中一个左

  7. android – Kotlin自定义获取执行方法调用

    像这样的东西:仍在使用Kotlin并且不确定get()方法是否会引用编辑器而不是创建新的编辑器.解决方法第二个属性声明适合您的需要:它有一个customgetter,因此获取属性值将始终执行getter,并且不存储该值.你可能会被等号get()=…

  8. android – Kotlin合成扩展和几个包含相同的布局

    我找了一些这样的:我在Studio中看到我可以访问dayName但是dayNameTextView引用了哪一个?正常,如果我只有一个包含的布局,它工作正常.但现在我有多次包含相同的布局.我当然可以这样做:但我正在寻找好的解决方案.版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  9. android – java.lang.IllegalArgumentException:指定为非null的参数为null:方法kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull

    我收到了这个错误java.lang.IllegalArgumentException:指定为非null的参数为null:方法kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull,参数事件为线覆盖funonEditorAction(v:TextView,actionId:Int,event:KeyEvent)以下是整个代码.这段代码最初是在ja

  10. android – Kotlin:如何访问CustomView的Attrs

    我在Kotlin中创建了一个自定义视图,并希望访问它的属性资源.以下是我的代码请注意,这将在init函数的attrs中出错.我想知道如何进入attrs?

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部