为什么我要改用kotlin

技术小黑屋 技术小黑屋     2022-08-31     307

关键词:

写在前面的话,作为一个不熬夜的人,一觉醒来发现Kotlin成为了Android的官方语言,可谓是大喜过望。为了趁热打铁,我决定提前三天放出原定本周日Release的文章。希望能及时让大家了解一下Kotlin。

相信很多开发人员,尤其是Android开发者都会或多或少听说过Kotlin,当然如果没有听过或者不熟悉也没有关系。因为本篇文章以及博客后期的内容会涉及到很多关于Kotlin的知识分享。

在写这篇文章前的一个多月,Flipboard中国的Android项目确定了正式将Kotlin作为项目开发语言,这就意味着新增的代码文件将以Kotlin代码格式出现,而且同时旧的Java代码也将会陆陆续续翻译成Kotlin代码。在使用Kotlin的这段时间,被它的简洁,高效,快捷等等特点震撼,所以有必要写一篇文章来谈一谈Kotlin的特性,如若能取得推广Kotlin的效果则倍感欣慰。

Kotlin的“简历”

  • 来自于著名的IDE IntelliJ IDEA(Android Studio基于此开发) 软件开发公司 JetBrains(位于东欧捷克)
  • 起源来自JetBrains的圣彼得堡团队,名称取自圣彼得堡附近的一个小岛(Kotlin Island)
  • 一种基于JVM的静态类型编程语言

来自知名的工具开发商JetBrains,也就决定了Kotlin的基因中必然包含实用与高效等特征。那我们接下来看一看Kotlin的特点,当然这也是我改用Kotlin的重要原因。

语法简单,不啰嗦

//variables and constants
var currentVersionCode = 1   //变量当前的版本号,类型Int可以根据值推断出来
var currentVersionName : String = "1.0" //显式标明类型
val APPNAME = "droidyue.com" //常量APPNAME 类型(String)可以根据值推断出来

//methods
fun main(args: Array<String>) {
    println(args)
}

// class
class MainActivity : AppCompatActivity() {

}

// data class  自动生成getter,setting,hashcode和equals等方法
data class Book(var name: String, val price: Float, var author: String)

//支持默认参数值,减少方法重载
fun Context.showToast(message: String, duration:Int = Toast.LENGTH_LONG) {
    Toast.makeText(this, message, duration).show()
}
  • Kotlin支持类型推断,没有Java那样的啰嗦。
  • 另外用var表示变量,val表示常量更加的简洁
  • 方法也很简单,连function都缩写成了fun,平添了几分双关之意。
  • 类的继承和实现很简单,使用:即可
  • Kotlin每个句子都不需要加分号(;)

空指针安全

空指针(NullPointerException或NPE)是我们使用Java开发程序中最常见的崩溃了。因为在Java中我们不得不写很多防御性的代码,比如这样

public void test(String string) {
    if (string != null) {
        char[] chars = string.toCharArray();
        if (chars.length > 10) {
            System.out.println(((Character)chars[10]).hashCode());
        }
    }
}

在Kotlin中空指针异常得到了很好的解决。

  • 在类型上的处理,即在类型后面加上?,即表示这个变量或参数以及返回值可以为null,否则不允许为变量参数赋值为null或者返回null
  • 对于一个可能是null的变量或者参数,在调用对象方法或者属性之前,需要加上?,否则编译无法通过。

如下面的代码就是Kotlin实现空指针安全的一个例子,而且相对Java实现而言,简直是一行代码搞定的。

fun testNullSafeOperator(string: String?) {
    System.out.println(string?.toCharArray()?.getOrNull(10)?.hashCode())
}

testNullSafeOperator(null)
testNullSafeOperator("12345678901")
testNullSafeOperator("123")

//result
null
49
null

关于空指针安全的原理,可以参考这篇文章研究学习Kotlin的一些方法

支持方法扩展

很多时候,Framework提供给我们的API往往都时比较原子的,调用时需要我们进行组合处理,因为就会产生了一些Util类,一个简单的例子,我们想要更快捷的展示Toast信息,在Java中我们可以这样做。

public static void longToast(Context context, String message) {
    Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}

但是Kotlin的实现却让人惊奇,我们只需要重写扩展方法就可以了,比如这个longToast方法扩展到所有的Context对象中,如果不去追根溯源,可能无法区分是Framework提供的还是自行扩展的。

fun Context.longToast(message: String) {
    Toast.makeText(this, message, Toast.LENGTH_LONG).show()
}
applicationContext.longToast("hello world")

注意:Kotlin的方法扩展并不是真正修改了对应的类文件,而是在编译器和IDE方面做得处理。使我们看起来像是扩展了方法。

Lambda, 高阶函数,Streams API, 函数式编程支持

所谓的Lambda表达式是匿名函数,这使得我们的代码会更加的简单。比如下面的代码就是lambda的应用。

findViewById(R.id.content).setOnClickListener {
    Log.d("MainActivity", "$it was clicked")
}

所谓的高阶函数就是

  • 可以接受函数作为参数
  • 也可以返回函数作为结果

举一个接受函数作为参数的例子。在Android开发中,我们经常使用SharedPreference来存储数据,如果忘记调用apply或者commit则数据修改不能应用。利用Kotlin中的高阶函数的功能,我们能更好的解决这个问题

fun SharedPreferences.editor(f: (SharedPreferences.Editor) -> Unit) {
    val editor = edit()
    f(editor)
    editor.apply()
}

//实际调用
PreferenceManager.getDefaultSharedPreferences(this).editor {
    it.putBoolean("installed", true)
}

当然这上面的例子中我们也同时使用了方法扩展这个特性。

Kotlin支持了Streams API和方法引用,这样函数式编程更加方便。比如下面的代码就是我们结合Jsoup,来抓取某个proxy网站的数据,代码更加简单,实现起来也快速。

fun parse(url: String): Unit {
    Jsoup.parse(URL(url), PARSE_URL_TIMEOUT).getElementsByClass("table table-sm")
        .first().children()
        .filter { "tbody".equals(it.tagName().toLowerCase()) }
        .flatMap(Element::children).forEach {
            trElement ->
            ProxyItem().apply {
                trElement.children().forEachIndexed { index, element ->
                    when (index) {
                        0 -> {
                            host = element.text().split(":")[0]
                            port = element.text().split(":")[1].toInt()
                        }
                        1 -> protocol = element.text()
                        5 -> country = element.text()
                    }
                }
            }.let(::println)
        }
}

字符串模板

无论是Java还是Android开发,我们都会用到字符串拼接,比如进行日志输出等等。在Kotlin中,字符串模板是支持的,我们可以很轻松的完成一个字符串数组的组成

val book = Book("Thinking In Java", 59.0f, "Unknown")
val extraValue = "extra"
Log.d("MainActivity", "book.name = ${book.name}; book.price=${book.price};extraValue=$extraValue")

注意:关于字符串拼接可以参考这篇文章Java细节:字符串的拼接

与Java交互性好

Kotlin和Java都属于基于JVM的编程语言。Kotlin和Java的交互性很好,可以说是无缝连接。这表现在

  • Kotlin可以自由的引用Java的代码,反之亦然。
  • Kotlin可以现有的全部的Java框架和库
  • Java文件可以很轻松的借助IntelliJ的插件转成kotlin

Kotlin应用广泛

Kotlin对Android应用开发支持广泛,诸多工具,比如kotterknife(ButterKnife Kotlin版),RxKotlin,Anko等等,当然还有已经存在的很多Java的库都是可以使用的。

除此之外,Kotlin也可以编译成Javascript。最近使用Kotlin写了一段抓取proxy的代码,实现起来非常快捷。甚至比纯JavaScript实现起来要快很多。

fun handle(): Unit {
        window.onload = {
            document.getElementsByClassName("table table-sm").asList().first()
                    .children.asList().filter { "TBODY".equals(it.tagName.toUpperCase()) }
                    .flatMap { it.children.asList() }.forEach {
                var proxyItem = ProxyItem()
                it.children.asList().forEachIndexed { index, element ->
                    when (index) {
                        0 -> {
                            proxyItem.host = element.trimedTextContent()?.split(":")?.get(0) ?: ""
                            proxyItem.port = element.trimedTextContent()?.split(":")?.get(1)?.trim()?.toInt() ?: -1
                        }
                        1 -> proxyItem.protocol = element.trimedTextContent() ?: ""
                        5 -> proxyItem.country = element.trimedTextContent() ?: ""
                    }
                }.run {
                    console.info("proxyItem $proxyItem")
                }

            }
        }
    }

关于性能

Kotlin的执行效率和Java代码的执行效率理论上一致的。有时候Kotlin可能会显得高一些,比如Kotlin提供了方法的inline设置,可以设置某些高频方法进行inline操作,减少了运行时的进栈出栈和保存状态的开销。

读到这里,是不是想要尝试一下Kotlin呢,它简洁的语法,汇集诸多特性,高效率实现等等,已经在国外风生水起,国外的Pintereset, Square, Flipboard等公司已经开始应用到生产中。

关于转向Kotlin

其实,我在做决定之前(当时Kotlin还没有被钦定)也曾有过考虑,是不是选择了Kotlin就意味着放弃Java呢,冷静下来想一想,其实并不是那么回事,因为Kotlin与Java语法太相近,以及在Kotlin中无时无刻不在和Java相关的东西打交道,所以这点顾虑不是问题的。

对于个人的项目来转向Kotlin,通常不是很难的选择,毕竟Kotlin是那么优秀的语言,相信很多人还是愿意尝试并使用这个事半功倍的语言的。

而比较难抉择的情况是如果如何让团队转用Kotlin,个人认为团队难以转用的原因有很多,比如学习成本,历史包袱等等。但其实根本原因还是思维方式的问题,歪果仁喜欢用工具来提升开发效率,因为人力成本很高。而国内团队提高效率的办法通常是增加成员。好在Flipboard 美国团队自2015年(可能更早)就引入了Kotlin,因此中国团队这边选用Kotlin也更加顺水推舟。当然更主要的是目前团队规模不大,成员一致认可Kotlin的优点。

关于团队转用Kotlin的方法,一般比较行得通的办法是自上而下的推行。这就意味着要么直接的技术负责人比较开明要么就是需要有人来不断推介来影响团队。

做个比较现实的比拟,Java就像是一趟从我的家乡保定开往北京西的耗时将近2个小时甚至更长的普通列车,而Kotlin则是那趟仅需40分钟就能到达的高铁。通常的人都会选择高铁,因为它节省了时间和提高了体验。这个时间和体验对应编程中的,我想应该是高效率和高可读性,可维护性的代码。

现在好了,有了Google的支持,Kotlin转Android相信在不久的将来就会全面展开。篡改Python的一句名言“人生苦短,我用Kotlin”,这样一个高效实用的语言应该会被越来越多的团队所接受,并应用到开发生产中。当然也希望在国内环境下大放异彩。

阅读更多内容,请访问技术小黑屋 或者关注技术小黑屋公众账号。
技术分享




android为什么要从java改用kotlin

Android为什么要从Java改用Kotlin->返回总目录<-文章目录一、Kotlin1、Kotlin是来自哪个公司2、为什么要学习Kotlin二、Android的Kotlin优先方法1、为什么要优先使用Kotlin进行Android开发?2、Kotlin优先意味着什么?一、Kotlin1、Kotlin是来... 查看详情

kotlin官网文档教程视频资源

...区开始用Kotlin之前将Kotlin用于生产环境:你在犹豫什么?为什么我要改用Kotlin?用Kotlin开发Andr 查看详情

kotlin-stdlib-jre7 已弃用。请改用 kotlin-stdlib-jdk7

】kotlin-stdlib-jre7已弃用。请改用kotlin-stdlib-jdk7【英文标题】:kotlin-stdlib-jre7isdeprecated.Pleaseusekotlin-stdlib-jdk7instead【发布时间】:2018-10-2423:00:46【问题描述】:昨天我更新了AndroidStudio版本和Kotlin插件版本。AndroidStudio版本:3.1.2Kotlin... 查看详情

Kotlin 泛型 Array<T> 导致“不能将 T 用作具体类型参数。请改用类”但 List<T> 不会

...Kotlin泛型Array<T>导致“不能将T用作具体类型参数。请改用类”但List<T>不会【英文标题】:KotlingenericsArray<T>resultsin"CannotuseTasareifiedtypeparameter.Useaclassinstead"butList<T>doesnot【发布时间】:2022-01-1702:36:17【问题... 查看详情

kotlin从基础到开发-总目录

...必读Android源码中com.android.support依赖迁移到AndroidX库Android为什么要从Java改用KotlinAndroid工程java项目如何转kotlin一、Kotlin基础教程1、androidstudio下载安装AndroidStudio如何更新至最新版本4.2.22、数据类型Kotlin基础(一)数据类型:var和... 查看详情

再见,java。你好,kotlin

...先采用Kotlin进行Android开发,并且也坚守了这一承诺。为什么要优先使用Kotlin进行Android开发?富有表现力且简洁:您可以使用更少的代码实现更多的功能。表达自己的想法,少编写样板代码。在使用Kotlin的专业开... 查看详情

kotlin快速入坑指南(干货型文档)(代码片段)

...10点下班,其实需求很多,我也要用这腐朽的声带喊出:我要学习,我要写文章!!又是一篇Kotlin的文章,为啥...还不是因为工作需要。毫无疑问,最好的学习方式是通过官方文档去学习。不过个人觉得官方文档多多少少 查看详情

DiffUtil 在嵌套的 recyclerview Kotlin 中不起作用

...图。在我使用notifyDataSetChanged之前,我的视图不会更新。我要求类似类型的issue,但这次我有Github链接。所以请看看并向我解释我做错了什么。谢谢MainActi 查看详情

kotlin初学者为什么要学kotlin

...焉;择其善者而从之,其不善者而改之。🔥为什么学Kotlin        Java用的挺好,为什么要学Kotlin?这是我之前的想法,但是越往后,这个想法慢慢的变淡。为什么?往下看,楸~💥薪资... 查看详情

kotlin以战养战为什么要学kotlin

...xff1a;一个分享Android相关知识·面试题库的好去处。🔥为什么学Kotlin        Java用的挺好,为什么要学Kotlin?这是我之前的想法,但是越往后,这个想法慢慢的变淡。为什么?往下看,楸~💥薪资... 查看详情

为什么要学习kotlin

(1)Google在2019年的I/O大会上宣布,Kotlin已经成为Android的第一开发语言。(2)GooglePlay商店中排名前1000的App里,有超过60%的App已使用Kotlin语言。(3)未来提供的官方API也将会有优先考虑Kotlin版本。&... 查看详情

为什么你必须摒弃java,全面转向kotlin语言?

...语言了!我想告诉你一个名为Kotlin的新的编程语言,以及为什么你要开始考虑使用它来开发你的下一个项目。我以前喜欢Java,但是去年我发现了Kotlin,只要有可能我就会用Kotlin来写代码。现在我实在无法想象有什么地方只有Java... 查看详情

访问公共类 (Kotlin)

...到了这个问题问题很简单:我有两个kotlin类(MainActivity和为什么)。为什么包含我想在MainActivity中调用的函数测试。我该怎么做?在本教程中,我只是在M 查看详情

为什么推荐你用kotlin语言?

  谷歌大牛说:为什么Kotlin比你们用的那些垃圾语言都好  原标题:谷歌大牛说:为什么Kotlin比你们用的那些垃圾语言都好编译:伯乐在线/黄小非【伯乐在线/程序员的那些事导读】:5月18日,安卓团队在谷歌I/O2017... 查看详情

为什么我放弃使用kotlin中的协程?(代码片段)

为什么我放弃使用Kotlin中的协程?实不相瞒,我对Kotlin这门编程语言非常喜欢,尽管它有一些缺点和奇怪的设计选择。我曾经参与过一个使用Kotlin、Kotlin协程(coroutine,下同)和基于协程的服务器框架KTOR的中型项目。这个技术组... 查看详情

<angled> 包含找不到“libxml/xmlversion.h”文件;改用“引号”

...07-0109:21:22【问题描述】:这些错误在16个文件中显示。当我要更改时,它会显示弹出窗口或点击解锁我的问题是这个- 查看详情

什么?你还不会用kotlin?一起跟着官方文档学习kotlin协程吧(代码片段)

为什么学Kotlin?Java用的挺好,为什么要学Kotlin?这是我之前的想法,但是越往后,这个想法慢慢的变淡。为什么?往下看:薪资以前找工作以Java为主,Kotlin优先(Kotlin属于加分项)现在找... 查看详情

如何将 Java 源文件的一部分转换为 Kotlin?

...otlin。将Java文件转换为Kotlin的菜单项被禁用,因为它不是我要转换的整个文件。如何将Java代码转换为Kotlin?【问题讨论】:您想将Java代码转换为K 查看详情