新闻资讯

新闻资讯 媒体报道

为什么要从Java切换到Kotlin

编辑:011     时间:2022-07-14

我想介绍一种新的编程语言Kotlin以及为什么要在下一个项目中考虑它。我曾经更喜欢Java,但是慢慢发现自己会尽可能地编写Kotlin代码。

Kotlin是由JetBrains开发和维护,它的务实简洁使编码令人有满意且高效的体验。出于以下一些原因,您可以考虑切换到Kotlin:

#0 与Java的互操作性

Kotlin是100%与Java兼容的,也就是可以用Kotlin和Java混合编程。您实际上可以使用Kotlin继续旧的Java项目上的工作。所有你喜欢的Java框架仍然可用,且无论您是用Kotlin编写的任何框架,都容易被您的Java朋友所采用。

#1 熟悉的语法

Kotlin不是学术界出生的怪异语言。它的语法对于来自面向对象领域的程序员来说都会比较熟悉。当然有一些与Java的差异,例如重新构造的构造函数或val/var变量声明。下面的代码段介绍了大多数基础知识:

class Foo {

    val b: String = "b" // val means unmodifiable var i: Int = 0 // var means modifiable fun hello() {
        val str = "Hello" print("$str World")
    } fun sum(x: Int, y: Int): Int { return x + y
    } fun maxOf(a: Float, b: Float) = if (a > b) a else b

}

#2字符串插值

比Java的String.format()更智能、更易读的字符串处理:

val x = 4 val y = 7 print("sum of $x and $y is ${x + y}") // sum of 4 and 7 is 11

#3 类型推断

Kotlin会在可提高可读性的任何地方推断您的类型:

val a = "abc" // type inferred to String val b = 4 // type inferred to Int val c: Double = 0.7 // type declared explicitly val d: List = ArrayList() // type declared explicitly

#4智能Cast

Kotlin编译器会跟踪您的逻辑并自动cast类型(如果可能),这意味着不再需要用instanceof检查后进行显式强制转换:

if (obj is String) {
    print(obj.toUpperCase()) // obj is now known to be a String }

#5相等判断

你可以停止显示调用equals(),因为==操作现在可以直接检查结构是否相等:

val john1 = Person("John")
val john2 = Person("John")
john1 == john2 // true  (structural equality) john1 === john2 // false (referential equality)

#6默认参数

无需使用不同的参数定义几种类似的方法:

fun build(title: String, width: Int = 800, height: Int = 600) {
    Frame(title, width, height)
}

#7命名参数

与默认参数结合使用时,命名参数消除了对Builder的需要:

build("PacMan", 400, 300) // equivalent build(title = "PacMan", width = 400, height = 300) // equivalent build(width = 400, height = 300, title = "PacMan") // equivalent

#8when表达式

switch被更具可读性和灵活性的when表达式取代:

print("x is 1") 2 -> print("x is 2") 3, 4 -> print("x is 3 or 4")
    in 5..10 -> print("x is 5, 6, 7, 8, 9, or 10") else -> print("x is out of range")
}

它既可以用作表达式或语句,也可以带有或不带有参数:

val res: Boolean = when {
    obj == null -> false obj is String -> true else -> throw IllegalStateException()
}

#9属性

自定义set & get可以将行为添加到公共字段中,这意味着我们可以停止漫不经心的getters & setters代码膨胀。


#10Data Class

这是一个POJO,带有toString(),equals(),hashCode()和copy(),与Java不同的是,它非常简介而不会占用上100行代码:

data class Person(val name: String,
                  var email: String,
                  var age: Int) val john = Person("John", "john@gmail.com", 112)

#11操作符重载

可以重载一组预定义的运算符以提高可读性:

data class Vec(val x: Float, val y: Float) { operator fun plus(v: Vec) = Vec(x + v.x, y + v.y)
}

val v = Vec(2f, 3f) + Vec(4f, 1f)

#12解构声明

某些对象可以被解构,例如对于迭代Map很有用:

for ((key, value) in map) { print("Key: $key") print("Value: $value")
}

#13范围

出于可读性考虑:

for (i in 1..100) { ... } for (i in 0 until 100) { ... } for (i in 2..10 step 2) { ... } for (i in 10 downTo 1) { ... } if (x in 1..10) { ... }

#14扩展功能

还记得在JAVA中第一次对List排序吗?您找不到sort()函数,所以你必须问你的导师或谷歌来学习Collections.sort()。后来当你需要将一个String转大写时,您最终编写了自己的辅助函数,因为您不知道StringUtils.capitalize()。

如果只有一种方法可以向旧类添加新功能;这样,您的IDE可以帮助您在代码补全中找到正确的函数/方法。在Kotlin中,您可以执行以下操作:

fun String.replaceSpaces(): String { return this.replace(' ', '_')
}

val formatted = str.replaceSpaces()

标准库扩展了Java原始类型的功能,这对于String非常有必要:

str.removeSuffix(".txt")
str.capitalize()
str.substringAfterLast("/")
str.replaceAfter(":", "classified")

#15Null安全

Java是我们应该称之为的几乎静态类型的语言。JAVA中,一个String类型变量是不保证的一定指向一个String-它可能是指null。即使我们已经习惯了它,但它否定了静态类型检查的安全性,因此Java开发人员不得不时刻小心NPE(Null Pointer Exception)。

Kotlin通过区分非空类型可为空的类型解决这个问题。类型默认情况下为非null,并且可以通过添加一个?来允许空值,像这样:

var a: String = "abc" a = null // compile error var b: String? = "xyz" b = null // no problem

每当您访问可为空的类型时,Kotlin在编译时会强制报错防止NPE:

val x = b.length        // compile error: b might be null

尽管这看起来很麻烦,但由于Kotlin的一些智能功能,可以轻易搞定——因为有智能的类型转换,它会尽可能将可空类型转换为非空类型:

if (b == null) return val x = b.length // no problem

我们也可以使用安全的调用?.,其结果可为null而不抛出NPE:

val x = b.length // compile error: b might be null

可以将安全调用链接在一起,以避免我们在其他语言有时会遇到的编写嵌套if-not-null检查的问题。另外如果我们需要默认值而不是null,我们可以使用三目运算符?::

val name = ship?.captain?.name ?: "unknown"

如果这些都不适合您,并且您确实需要NPE,则必须明确要求:

val x = b?.length ?: throw NullPointerException() // same as below val x = b!!.length // same as above

#16更好的Lambda

Kotlin有一个很好的lambda系统-由于一些聪明的设计选择,在可读性和简洁性之间达到了完美的平衡。首先语法是一目了然的:

val sum = { x: Int, y: Int -> x + y } // type: (Int, Int) -> Int val res = sum(4,7) // res == 11

这里有一些聪明的地方:

  1. 如果lambda是方法的最后一个或唯一的参数,则可以移动或省略方法的圆括号。
  2. 如果我们选择不声明单参数lambda的参数,则会隐式声明it作为名称。

这些事实加在一起使得以下三行等效:

numbers.filter({ x -> x.isPrime() })
numbers.filter { x -> x.isPrime() }
numbers.filter { it.isPrime() }

这使我们可以编写简洁漂亮的方法代码:

persons
    .filter { it.age >= 18 }
    .sortedBy { it.name }
    .map { it.email }
    .forEach { print(it) }

Kotlin的lambda系统与扩展功能相结合,非常适合DSL创建。查看 Anko 以旨在增强Android开发的DSL为例:

verticalLayout {
    padding = dip(30)
    editText {
        hint = “Name”
        textSize = 24f }
    editText {
        hint = “Password”
        textSize = 24f }
    button(“Login”) {
        textSize = 26f }
}
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

回复列表

相关推荐