当前位置: 首页>>编程语言>>正文


为什么要从Java切换到Kotlin

为什么您应该从Java完全切换到Kotlin

是时候开始使用现代编程语言了!

 

我想介绍一种新的编程语言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
    }
}

#17IDE支持

如果您打算开始使用Kotlin,可以有很多选择,但是我强烈建议您使用IntelliJ, 这个IDE直接与Kotlin捆绑在一起-其功能展示了由同一个人设计语言和IDE的优势。

仅举一个小巧而巧妙的例子,当我第一次尝试从Stack Overflow复制粘贴一些Java代码时,便会弹出此内容:

IntelliJ将通知您是否将Java代码粘贴到Kotlin文件中

到此为止。感谢您的阅读!

参考资料

本文由《纯净天空》出品。文章地址: https://vimsky.com/article/4538.html,未经允许,请勿转载。