您的位置 首页 java

什么是Kotlin?解释Java的替代品

JVM 和Android开发方面, Kotlin Java 有很大的优势,并且在相同的项目中比Java发挥得很好。

Kotlin是一种通用的、免费的、开源的、静态类型的 “实用主义 “编程语言,最初是为JVM( Java虚拟机 )和Android设计的,并结合了面向对象和函数式编程的特点。它专注于互操作性、安全性、清晰性和工具支持。

针对JavaScript ES5.1和一些处理器的本地代码(使用 LLVM )的Kotlin版本也在生产中。

Kotlin于2010年起源于 JetBrains ,即 IntelliJ IDEA 背后的公司,并从2012年开始开放源代码。 GitHub 上的Kotlin项目有超过770个贡献者;虽然大部分团队在JetBrains工作,但Kotlin项目也有近100个外部贡献者。JetBrains在其许多产品中使用Kotlin,包括其旗舰产品IntelliJ IDEA。

Kotlin是一种更简洁的Java语言

乍一看,Kotlin像是一个更简洁、更精简的Java版本。请看上面的截图,将一个Java代码样本(在左边)自动转换为Kotlin。请注意,在实例化Java变量时固有的类型重复已经消失了。例如:

  StringBuilder  sb = new StringBuilder();  

在Kotlin中

 val sb = StringBuilder()  

你可以看到,函数是用fun关键字定义的,现在 分号 在出现换行时是可选的。val关键字声明了一个只读的属性或局部变量。同样地, var 关键字声明了一个可变的属性或局部变量。

然而,Kotlin是强类型的。val和var关键字只有在类型可以推断的情况下才可以使用。否则你需要声明类型。类型推断似乎随着Kotlin的每一个版本的发布而不断改进。

请看一下两个窗格顶部附近的函数声明。在Java中,返回类型在原型之前,但在Kotlin中,返回类型在原型之后,与 Pascal 中一样用冒号标出。

从这个例子中并不完全明显,但Kotlin已经放宽了Java的要求,即函数是类成员。在Kotlin中,函数可以在文件的顶层声明,也可以在其他函数的局部声明,还可以作为类或对象的成员函数,以及作为扩展函数。扩展函数提供了类似于C#的能力,可以用新的功能来扩展一个类,而不需要从该类中继承,也不需要使用任何类型的设计模式,如装饰器。

对于 Groovy 粉丝来说,Kotlin实现了构建器;事实上,Kotlin构建器可以进行类型检查。Kotlin支持委托属性,它可以用来实现懒惰属性、可观察属性、可否决属性和映射属性。

许多在其他语言中可用的异步机制可以使用Kotlin coroutines作为库实现。这包括C#和ECMAScript的async/await, Go 的channel和select,以及C#和 Python 的generators/yield。

Kotlin中的函数式编程

允许顶层函数只是Kotlin函数式编程故事的开始。该语言还支持高阶函数、匿名函数、lambdas、内联函数、 闭包 、尾部递归和泛型。换句话说,Kotlin拥有函数式语言的所有特性和优势。例如,考虑以下功能型Kotlin的习惯用语。

在Kotlin中过滤一个列表

 val positives = list.filter { x -> x > 0 }  

对于一个更短的表达式,当λ函数中只有一个参数时,可以使用它。

 val positives = list.filter { it > 0 }  

在Kotlin中遍历一个成对的map/list

 for ((k, v) in map) { pr Int ln(“$k -> $v”) }  

k和v可以被称为任何类型。

在Kotlin中使用范围

 for (i in 1..100) { ... }  // closed range: includes 100
for (i in 1 until 100) { ... } // half-open range: does not  include  100
for (x in 2..10 step 2) { ... }
for (x in 10 downTo 1) { ... }
if (x in 1..10) { ... }  

上面的例子显示了for关键字以及范围的使用。

尽管Kotlin是一种成熟的函数式编程语言,但它保留了Java的大部分面向对象的特性,作为一种替代的编程风格,这在转换现有的Java代码时非常方便。Kotlin有带构造函数的类,以及嵌套类、内层类和匿名内层类,而且它有像Java 8那样的接口。Kotlin没有一个new关键字。要创建一个类实例,就像普通函数一样调用 构造函数 。我们在上面的截图中看到了这一点。

Kotlin有从一个命名的超类的单继承,所有Kotlin类都有一个默认的超类Any,它与Java的基类java.lang.Object不一样。Any只包含三个预定义的成员函数:equals(), hashCode (), and toString()。

Kotlin类必须用open关键字标记,以允许其他类继承它们;而Java类则有点相反,除非用final关键字标记,否则它们是可以继承的。要覆盖一个超类的方法,该方法本身必须被标记为 open ,而子类的方法必须被标记为 override 。这与Kotlin的理念是一致的,即把事情明确化,而不是依赖默认值。在这个特殊的案例中,可以看到Kotlin将基类成员明确标记为开放继承,将派生类成员标记为覆盖,这种方式避免了几种常见的Java错误。

Kotlin的安全特性

说到避免常见的错误,Kotlin的设计是为了消除空指针引用的危险并简化空值的处理。它通过使标准类型的null成为非法的来实现这一点,增加了可空值类型,并实施快捷的符号来处理对null的测试。

例如,一个 String 类型的常规变量不能持有null。

 var a: String = "abc" 
a = null // compilation error  

如果你需要允许 空值 ,例如用来保存 SQL 查询结果,你可以通过在类型上附加一个问号来声明一个可空的类型,例如String?

 var b: String? ="abc"
b = null // ok  

这些保护措施更进一步。你可以肆无忌惮地使用非空值类型,但你必须在使用空值类型之前测试它的空值。

为了避免空值测试通常需要的冗长语法,Kotlin引入了一个安全调用,写成?. 例如:b?.length,在b不为空时返回b.length,否则为null。这个表达式的类型是Int?.

换句话说,b?.length是if (b != null) b.length else null的一个快捷方式。这种语法很好地连接起来,消除了很多冗长的逻辑,特别是当一个对象从一系列的数据库查询中填充时,其中任何一个都可能失败。例如,bob?.department?.head?.name将返回Bob的部门主管的名字,如果Bob、部门和部门主管都是非空的。

为了只对非空值进行某种操作,你可以使用安全调用操作符?.和let:。

 val listWithNulls: List<String?> = listOf("A", null) 
for (item in listWithNulls) {
       item?.let { println(it) } // prints A and ignores null }  

通常你想从一个可归零的表达式中返回一个有效但特殊的值,通常这样你就可以把它保存到一个不可归零的类型中。这方面有一种特殊的语法,写成?:

 val l = b?.length ?: -1  

相当于

 val l: Int = if (b != null) b.length else -1  

同样地,Kotlin省略了Java的检查异常,即必须捕获的可抛出条件。例如, JDK 的签名

  Appendable   append (CharSequence csq) throws IO exception ;  

要求你在每次调用append方法时都要捕获IOException。

 try {
  log.append(message)
}
catch (IOException e) {
  // Do something with the exception
}  

Java的设计者认为这是个好主意,只要 程序员 在catch子句中实现一些合理的东西,这对简单程序来说是个好事。然而,在大型的Java程序中,你经常看到这样的代码:强制性的catch子句中只包含一个注释。//todo: handle this. 这对任何人都没有帮助,而且检查异常对大型程序来说是一种净损失。

Kotlin Coroutines

Kotlin中的Coroutines本质上是轻量级线程。你在一些CoroutineScope的上下文中用launch coroutine builder启动它们。最有用的coroutine作用域之一是runBlocking{},它适用于其代码块的范围。

 import kotlinx.coroutines.*

fun main() = runBlocking { // this: CoroutineScope
    launch { // launch a new coroutine in the scope of runBlocking
        delay(1000L) // non-blocking delay for 1 second
        println("World!")
    }
    println("Hello,")
}  

这段代码产生以下输出,每行之间有一秒钟的延迟。

 Hello,
World!  

安卓的Kotlin

直到2017年5月,官方支持的Android编程语言只有Java和C++。 谷歌 在2017年谷歌I/O大会上宣布正式支持Android上的Kotlin,从Android Studio 3.0开始,Kotlin被内置到Android开发工具集。Kotlin可以通过一个插件添加到早期版本的 Android Studio 中。

Kotlin编译成与Java相同的字节码,以自然的方式与Java类互操作,并与Java共享其工具。因为在Kotlin和Java之间来回调用没有任何开销,所以在目前使用Java的Android应用中逐步添加Kotlin是非常合理的。少数情况下,Kotlin和Java代码之间的互操作性缺乏优雅,如Java的纯属性设置,但是很少遇到,也很容易解决。

早在2016年11月, Pinterest 就是用Kotlin编写的安卓应用的海报,在2017年谷歌I/O大会上,作为Kotlin公告的一部分,它被突出地提到。此外,Kotlin团队喜欢引用 Evernote 、Trello、 Gradle 、Corda、Spring和Coursera的安卓应用。

Kotlin vs Java

自Google I/O宣布以来,在Android社区中经常出现为新的开发选择Kotlin还是Java的问题,尽管在2016年2月Kotlin 1.0发布时人们已经在问这个问题。简短的回答是,Kotlin代码比Java代码更安全、更简洁,而且Kotlin和Java文件可以在Android应用中共存,因此Kotlin不仅对新的应用有用,而且对扩展现有的Java应用也有用。

我所看到的选择Java而不是Kotlin的唯一有说服力的论据是针对完全的Android开发新手的情况。对于他们来说,可能有一个障碍需要克服,因为从历史上看,大多数Android文档和例子都是用Java编写的。另一方面,在Android Studio中把Java转换为Kotlin是一个简单的问题,就是把Java代码粘贴到Kotlin文件中。在2022年,也就是Kotlin 1.0的六年之后,我不确定这种文档或例子的障碍是否仍然以任何重大方式存在。

对于几乎所有从事Android开发的人来说,Kotlin的优势是引人注目的。一个Java开发者学习Kotlin的典型时间是几个小时–这对于消除空参考错误、启用扩展函数、支持函数式编程和增加循环程序来说是一个很小的代价。 典型的粗略估计表明,从Java到Kotlin的代码行数大约减少40%。

Kotlin vs Scala

在Android社区,选择Kotlin还是Scala的问题并不经常出现。如果你看一下GitHub(截至2022年10月)并搜索Android仓库,你会发现大约有5万个使用Java,2.4万个使用Kotlin,以及73个使用Scala。是的,用Scala编写Android应用程序是可能的,但很少有开发者会去理会。

在其他环境中,情况则不同。例如,Apache Spark大部分是用Scala编写的, Spark 的大数据应用也经常用Scala编写。

在很多方面,Scala和Kotlin都代表了面向对象编程与函数式编程的融合,Java就是其中的典范。这两种语言有许多共同的概念和符号,例如使用val的不可变声明和使用var的可变声明,但在其他方面略有不同,例如在声明lambda函数时应将箭头放在哪里,以及是使用单箭头还是双箭头。Kotlin的数据类映射到Scala的case类。

Kotlin定义nullable变量的方式与Groovy、C#和F#类似;大多数人都能很快理解。另一方面,Scala使用Option monad来定义可归零的变量,这可能是非常禁止的,以至于一些作者似乎认为Scala没有归零安全性。

Scala的一个明显缺陷是它的编译时间往往很长,这一点在你从源代码中构建大型Scala主体时最为明显,比如Spark仓库。另一方面,Kotlin的设计是为了在最频繁的 软件开发 场景中快速编译,事实上它的编译速度往往比Java代码快。

Kotlin与Java的互操作性

在这一点上,你可能想知道Kotlin如何处理Java互操作性调用的结果,因为在空值处理和检查异常方面存在差异。Kotlin默默地、可靠地推断出所谓的 “平台类型”,它的行为与Java类型完全一样,也就是说,它是可空的,但可以产生空指针异常。Kotlin也可以在编译时向代码中注入一个断言,以避免触发一个实际的空指针异常。对于平台类型没有明确的语言符号,但是如果Kotlin必须报告一个平台类型,比如在错误信息中,它会在类型上加上!。

文章来源:智云一二三科技

文章标题:什么是Kotlin?解释Java的替代品

文章地址:https://www.zhihuclub.com/184599.shtml

关于作者: 智云科技

热门文章

网站地图