2分钟了解kotlin:优点,缺点,设计原则
来源:互联网 发布:mac pr防抖 编辑:程序博客网 时间:2024/06/02 01:04
1. 优点
kotlin提供了很多好的特性,比如:null安全检测,属性访问,unchecked exceptions, publication有更详细的介绍。
1.1 java 自动转换成kotlin
kotlin项目开发总结有介绍如何使用,这个是有JetBrains提供的,目前已经集成到了IDEA/AS, 虽然它不是很完美(我的上篇博客也已经介绍到了),但是对比重新用Kotlin开发一个完全一样功能的类来说,可以节省不少时间。
1.2 lateinit Delegates.notNull and lazy
kotlin的null安全监测是个非常好的特性,但是也有有个问题,比如:
var aMap: AMap? = nullonCreate(){ aMap = ... aMap!!.projection ....}
虽然我们可以保证aMap已经在onCreate方法定义了,但是因为我们在定义aMap的时候是AMap?类型,所以在以后使用的都必须使用aMap!!
来告诉编译器aMap不为null,会显得非常麻烦。幸运的是kotlin已经帮我们考虑到了应对方法
lateinit var name: Stringvar age: Int by Delegates.notNull<Int>()
通过上面两种方法,可以在定义的时候不提供初始化,可以延迟到需要的时候,但是就像我在kotlin项目开发总结说的,需要慎用,除非你能确保不会在后面遗漏掉重新赋值,否则会在运行时报空指针错误,这就浪费了kotlin的null安全监测这个非常好的特性。
lazy代理是个很好用的东西,就像下面这样的定义
val imm: InputMethodManager by lazy { getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager }
lazy后面跟着的block只会在你第一次read这个imm
的时候调用,以后读取imm
会直接返回block保存的值。在需要追求启动速度的APP可以很好的使用。
1.3 扩展后的collections
kotlin提供了很多对collections和iterables的扩展,具体可以看下
我写的分析和使用collections。
1.4 Named 和 默认的函数参数
Named 函数参数和默认函数参数非常简单,但有时候可以帮我们省掉很多代码。特别是当构造函数有超过4个以上的参数时,可以指定默认几个默认参数,在调用的时候可以只提供一个参数。比如
class Presenter( val okhttp: OkHttp = productionOkHttp(), val picasso: Picasso = productionPicassoInstance()) {...}
在调用的时候,我们不提供参数,那么默认参数会被使用
var prensenter = Presenter()
2. 缺点
虽然kotlin非常强大,但它毕竟不是完美的。它也会有一些可能未来会解决的缺点。
2.1 编译速度慢
大家在使用kotlin开发项目的时候应该有注意到了,主要还是因为kotlin会自动自动生成更多的代码,比如为属性生成get/set, 对比java会存在更多的方法数量。https://youtrack.jetbrains.com/issue/KT-6246,这篇博客有做分析
2.2 annotation processing的问题
我目前开发的项目使用了dagger,permissionsdispatcher,deeplinkdispatch,databinding,都需要使用kapt来做annotation proccessing,但是我已经碰到了好多次,kapt报的很奇怪的错误,有一次,我重构dagger的module时,报了一个蛋疼的问题,我以为我是dagger没用好,找了很多资料对比都没有解决,花了大概一天的时间,后面没办法只能clean project,但是奇怪的问题还在,后面我让application继承了DaggerApplication,clean下就可以。后面还是碰到好几次这样的问题,都是clean之后build就可以了,这个问题应该不只我一个人碰到,我想可能是kapt的一个bug, 我还是很相信google/JetBrains, 所以还是继续坚持使用kotlin开发项目。
2.3 没有命名空间
kotlin允许定义top-level的函数和属性,比如
//demo.ktvar a = "aa"fun printlnA(){ println(a)}
这可能是一个非常好的特性,但是也会有问题,比如在项目下面有两个甚至更多的printlnA
方法,那么在调用的时候(特别是在阅读代码),很难区分方法来自哪个地方,除非你F3
跳转到声明处。为了避免这个问题,你可以选择把printlnA
方法移到一个object中,比如
object PrintlnHelper{ fun printlnA(){ println(a) }}
让我们来看下kotlin和java的调用方式
//kotlinPrintlnHelper.printlnA()//javaPrintlnHelper.INSTANCE.printlnA()
为了避免如上在Java中调用的怪怪的。。,可以使用@JvmStatic注解该方法
object PrintlnHelper{ @JvmStatic fun printlnA(){ println(a) }}
通过上面的分析,对于有代码洁癖或者同时用Java和kotlin开发的项目,也是不够完美的,这个缺点是可以避免的,但是你需要花费一点时间去熟悉Kotlin
2.4 没有静态修饰语
还是像上面的问题,如果项目同时存在kotlin和Java,而且Java需要调用kotlin代码,看代码分析问题
//Javapublic class View { public static final int VISIBLE = 0x00000000; public static final int INVISIBLE = 0x00000004; public static View inflate(Context context, int resource) {...}}
使用kotlin使用同样的功能,如下:
class View { companion object { @JvmField val VISIBLE: Int = 0x00000000 @JvmField val INVISIBLE: Int = 0x00000004 @JvmStatic fun inflate(context: Context, resource: Int) {...} }}
下面是有@JvmField和没有的Java调用方式
// With annotations:View.VISIBLE;//Without annotations:View.Companion.getVISIBLE();
其实这个问题也不是很严重的,但是对比Java还是多了个@JvmField, 但是kotlin新手或者容易忘记,使用@JvmField,这个缺点可以通过熟悉kotlin来避免
2.5 Java自动转换成kotlin带来的问题
Java自动转换成kotlin是个非常好的特性,但是也会带来问题。Javadoc原来的结构会被破坏掉,静态field和方法会转换成companion object中的普通声明,如果有Java代码调用这个类,就会出现点问题,除非你后面手动给这个转换后的companion object 添加上@JvmField和@JvmStatic。这是个不小的隐患,需要特别注意下。
2.6 会增加方法数量
过多的方法数量会导致编译速度变慢。kotlin通过闭包,内联函数等可以显著减少代码的总行数,但它可能也会增加编译后的方法数量。对于Android项目来说这肯定是一个不小的缺点。有很多原因会导致方法数量增加,但是最大的来源是kotlin实现属性。
kotlin不像Java可以直接访问field, 而是通过创建property的方式来访问。这是一个很好的特性,你可以自定义实现property的set/get,对比Java的set/get方法是个很大的进步。
但是这个是有代价的,对于val
属性,kotlin自动生成backing field
和getter函数来供java调用。public var
属性会自动生成setter/getter函数。幸运的是private var
属性已经有默认的setter/getter,需要不需要额外生成。所以这个时候你想想如果你定义了很多个public var
和val
属性,那么kotlin会帮你自动生成更多的函数,所以带来的后果就是方法数量会越来越多,导致编译速度变慢。
假如方法数量已经接近限制,不需要使用自定义setter的属性可以用@JvmField修饰,被@JvmField修饰的属性不会自动生成setter/getter函数,如下
@JvmFieldvar aMap: aMap? = null
2.7 “==”
在kotlin中,”==”和”equals”都是比较引用是否相等。如何项目中只有kotlin代码,那这个肯定是个非常好的特性,但是如果项目同时包含java和kotlin(比如:你是在旧的java工程基础上,用kotlin开发新功能),那么“==”很容易产生混淆和错乱。
3. 设计原则
3.1
kotlin的class默认是final, 如果想要能被继承,那么需要使用open 修饰,它的设计原则来自于
Effective Java
这种默认的设计原则,会导致第三方/未完成的sdk的大多数会是不可继承的,从提供者角度来说:它必须保证这个类是足够完整的,从使用者角度来说:这个类必须要提供我需要的所有东西,否则,我必须重写。当然提供者可以为这个类加上open来表示这个类是可以继承的,但是这是另外一种设计思维。
Roedy Green, How to Write Unmaintainable Code有提到:
给你的所有类设置为final。 毕竟,你完成了这个项目 - 当然没有人可以通过扩展你的class来改善你的工作。 这甚至可能是一个安全漏洞 - 毕竟,为什么不是java.lang.String final? 如果您的项目中的其他编程人员抱怨,请告诉他们您的执行速度提升
3.2 错误的使用运算符重载
kotlin允许对类的变量运算符进行重载,设想有下面的代码
var person3 = person1 + person2
“+” 这个运算符有可能在很多个地方做了重载,在后期维护代码,很难区分哪个是哪个
运算符重载是有争议的,想要了解点击下面链接
- Operator Overloading Considered Harmful
- Operator Overloading Ad Absurdum
- Why Everyone Hates Operator Overloading
4.总结
kotlin有很多优点,你也可以通过很多方式去了解和学习kotlin,相反,我们可能更想知道它的缺点,因为我们不希望它会成为未来项目中的隐患,在以后的项目开发中会不断分享关于kotlin学习心得,欢迎大家加入”kotlin交流群”一起学习提高,群号是:248445350
- 2分钟了解kotlin:优点,缺点,设计原则
- 一分钟了解“表示优点/缺点/特性 的词汇”
- 23种设计模式(概念、原则、场景、优点、缺点、应用)简述
- 索引的优点和缺点 2
- 索引的优点和缺点----数据库设计、面试必看
- 网页设计采用div+css的优点和缺点
- IOMMU概念,优点,缺点
- maven 使用,优点,缺点
- WebService优点和缺点
- webservice优点和缺点
- Ajax优点和缺点
- Struts1 优点与缺点
- ibatis优点与缺点
- php优点和缺点
- GWT 优点和缺点
- 索引优点和缺点
- 决策树优点和缺点
- 优点缺点谈
- HTML第二天学习笔记
- 源码安装mongodb
- 27.1.1.3 Spark SQL 中ANTLR4的应用
- CentOS6.5 安装MySQL-Percona
- Stereo Matching文献笔记之(九):经典算法Semi-Global Matching(SGM)之神奇的HMI代价计算~
- 2分钟了解kotlin:优点,缺点,设计原则
- 安徽省电信暑期实习生面试
- 磁盘的挂载与卸载
- ROC曲线(Receiver Operating Characteristic Curve)
- maven第一天
- java接口interface详解
- 微信小程序--wx.request使用psot传递数据
- 谱聚类算法(Spectral Clustering)
- Linux系统-git远程库与原始库同步