函数式
Kotlin较Java一个很大的特性差异便是对函数式的支持大大提高了。我们知道函数式基本元素有:
-
不可变性
-
引用透明
-
无副作用
-
高阶函数与lambda表达式
-
Monad结构
-
柯里化
-
模式匹配
-
智能类型推断
-
递归
-
并发安全
函数式编程有如下等式:
程序 = 可变性程序 + 不可变性程序
可变性程序 = 对象 + 依赖关系
不可变程序 = 纯函数 + 组合 (Monad结构)
Kotlin的语言特性对此都做了支持,相比于Java在组件化和响应式上Kotlin更加简洁、直观。
类型差异
Kotlin和Java类型上的差异,有类型声明差异和类型体系差异。
类型声明差异
val a: String = “I am Kotlin”
这与函数定义时返回类型,类继承,接口实现提供了一致的书写体验
fun sum(x: Int, y: Int): Int {
Java是类型前置的写法,定义方法时返回类型写在了前面,但是继承和实现是后置的。类型后置的好处:通过类型推导实现类型省略时一致的书写体验;Kotlin做到了三种场景符号一致,书写一致(类型推导)
类型体系差异
下图是Kotlin类型体系,Kotlin把基本数据类型统一成对象类型,形成了面向对象的继承体系。
Kotlin的瑕疵
kotlin的语言特性丰富而有力,带来了与Java的特性差异。任何事物都有正、反两面,kotlin也不例外。
1)多维数组需要通过嵌套的方式创建
val bytes = Array(3) { ByteArray(4) }
对比一下Java
byte[][] bytes = new byte[3][4];
相比Kotlin的,Java清晰简便多了
2)Kotlin没法实现的接口样子
这样的Java接口
interface Itest{
在Kotlin里实现该接口,class A会因为实现了两个相同签名方法而报错
class A : Itest{
3)抛弃了受检异常(checked exception)
这是颇有争议的瑕疵,有坏处也有好处。
**坏处:**对异常不强制要求处理。有时候调用一些方法,特别涉及到硬件或者网络相关的方法,往往不一定知道它可能会抛出什么异常,或者根本不知道它会抛出异常。便会在这块地方遗漏了某些异常的处理或者没做异常处理,埋下一些潜在的问题。
**好处:**Kotlin不区分checked exception,这样能简化代码书写,符合Kotlin一贯的简洁设计理念。因此Kotlin是没有受检异常的。
Kotlin在收银台具体实践
Kotlin语言所拥有的特性为面向过程特性、面向对象特性和函数式特性的部分总和。从V9.2.2版本开始,安卓收银台模块开始全面使用Kotlin语言。为了稳定,我们采用了Java和Kotlin混合开发的模式。
01与Java的互操作
先来看看Kotlin和Java的互操作。
1)Kotlin调用Java的代码
几乎和Java调用Java代码相同,有几个不相同的点如下:
1.属性前缀
示意代码:
public final class User {
2.平台类型
kotlin调用Java代码后返回的类型在Kotlin侧叫做平台类型。平台类型既可当作可空类型也可作为非空类型。换句话说,kotlin编译时,平台类型被认为是非空类型,不需要非空判断顺利编译通过,在运行时被认为是可空类型。平台类型可能触发空指针异常。收银台空安全实践避免了这种空指针,详见后文内容。
2)Java调用Kotlin的代码
在kotlin代码上增加Kotlin注解,Java调用Kotlin便能像Java调用Java代码般
1)@JvmOverloads 默认参数重载
@JvmOverloads
引入默认参数重载的注解后,只需要一次方法定义就够满足收银台对底部支付文案的内容更新,减少了方法定义的模版代码。
2)@JvmStatic 静态
object Updater {
收银台是Java和Kotlin语言混合开发,通过这个注解,原来的Java代码调用Kotlin写的of方法就能成为我们熟知的Updater.of的样子。
3)在接口层面,Java使用Kotlin接口也做到了打通;
Java的接口 <—> Kotlin的接口 <—> Kotlin的lambda表达式
block: () -> ArrayList
收银台kotlin侧定义的lambda表达式,被Java调用时会被识别成Java的Function系列的接口。
02收银台的空安全实践
原生收银台项目本身的代码,截止目前未出现过空指针崩溃。空指针是客观存在的,收银台是如何避免了空指针呢?借助Kotlin主要做了两个方面的工作:
1.通过Kotlin可空类型和空安全调用特性,我们把非空的判断归整到上游的接口数据层,做统一集中式的处理
示意代码如下:
public class Response extends BaseEntity implements ICheckNull {
对每个接口返回的实体类,都实现ICheckNull接口,并检查实体类里每个对象是否为null,如果为null我们额外初始化这个对象。这套逻辑借助泛型封装成了收银台的工具类,方便其他实体类复用。
2. Kotlin的平台类型可能造成的空指针异常,因此对Kotlin调用Java的代码返回的类型处理为可空类型,即做一次非空判断。除非Java代码返回能保证非空
Java侧示意代码
public PayEntity createPayEntity(Payment payment) {
Kotlin调用Java
val payEntity: PayEntity? = Manager.getInstance().createPayEntity(payment)
除此之外利用Kotlin语言特性,我们更一步地提高了空安全。具体地说通过不可变性,属性读写分离,Elvis操作符等来实现。
1)可变与不可变性
variable = var ; value = val(final)
2)分离属性的读和写操作
Java的setter方法和getter方法内置到属性,方便分离读&写操作,有弹性。
示意代码
var age: Int = 0
3)空安全调用 & Elvis操作
Kotlin语言层面提供了便捷的空判断表达,避免了类似写Java代码通过大量if语句判空嵌套的情况。
val currentPlan: String? = defaultCard?.recommendId ?: DEFAULT_PLAN
03遇到的问题
-
反序列化:fastjson框架反序列化Kotlin定义的的Int、Float、Double类型时,变成null而不是Java的基本数据类型值,用String类型替换原来的字段类型。
-
平台编译失败:通过增加中间变量,变换写法而得到解决。
-
遗漏的异常处理:NumberFormatException崩溃
NumberFormatException崩溃日志如下:
—java.lang.NumberFormatException: empty String sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842) sun.misc.FloatingDecimal.parseFloat(FloatingDecimal.java:122) java.lang.Float.parseFloat(Float.java:451)
…
问题出在parseFloat(Float.java:451)方法上,看下toFloat的Kotlin实现:
@kotlin.internal.InlineOnly
Kotlin的toFloat方法内部调用了Java的parseFloat方法,Java的parseFloat源码如下:
/**
从源码上发现parseFloat方法会抛出NullPointerException和NumberFormatException两种异常,漏做了NumberFormatException异常处理,传入了空字符串。因此调用不是自己写的方法的时候要关注可能会抛出的异常。
从编程语言的历史进程看Kotlin,它是现代化的编译型、强类型、静态语言,符合语言多编程范式的发展潮流。语言特性相比Java更加函数式,并把一些Java编程的最佳实践沉淀到语言特性中。
收银台原生化对编程语言的选型,是基于对运行效率和开发效率之间的权衡;Kotlin是工具,正确的使用工具有助于我们更好地表达收银台的业务逻辑。使用Kotlin的过程是对过去Java编程思维进化的过程,这是Kotlin带来的额外收益。
收银台落地Kotlin过程中,我们消除了空指针异常,截止目前收银台自身业务代码没有空指针的异常。Kotlin原生化改造后,进入首页加载完成耗时由原来H5收银台1180ms左右到现在的360ms左右,渲染时间缩短了820ms,首屏加载时间缩短了69.5%。
在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了
很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘
如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。
2020最新上万页的大厂面试真题
七大模块学习资料:如NDK模块开发、Android框架体系架构…
只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
学习路线+知识梳理
花了很长时间,就为了整理这张详细的知识路线脑图。当然由于时间有限、能力也都有限,毕竟嵌入式全体系实在太庞大了,包括我那做嵌入式的同学,也不可能什么都懂,有些东西可能没覆盖到,不足之处,还希望小伙伴们一起交流补充,一起完善进步。
这次就分享到这里吧,下篇见。
[外链图片转存中…(img-fZ4e7IyR-1712055014094)]
[外链图片转存中…(img-lcz1gjDH-1712055014095)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-AgZ6m9HU-1712055014095)]
学习路线+知识梳理
花了很长时间,就为了整理这张详细的知识路线脑图。当然由于时间有限、能力也都有限,毕竟嵌入式全体系实在太庞大了,包括我那做嵌入式的同学,也不可能什么都懂,有些东西可能没覆盖到,不足之处,还希望小伙伴们一起交流补充,一起完善进步。
这次就分享到这里吧,下篇见。