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

我想告诉你一种叫做 Kotlin 的新编程语言,以及为什么你应该考虑用它进行你的下一个项目。我曾经更喜欢Java。但是去年,我发现可以在任何时候用Kotlin做我想做的事,我实在想不出Java会是一个更好的选择。

Kotlin是由JetBrains开发的,事实上,正是这些人开发了一整套IDE,正因为有IntelliJ和ReSharper的努力,现在的Kotlin 才会如此闪耀。它务实和简洁的语法,使编程成为一个令人满意和有效的体验。

尽管Kotlin可以编译JavaScript,而且很快能编译机器代码,但我在这里将主要专注于其环境,JVM。

这里是几个你们应该完全转向到Kotlin原因(没有特定的顺序):

0# 与Java的互操作性

Kotlin可以100%与Java进行互操作。你可以在Kotlin中继续使用你在旧Java项目中的代码。所有你喜欢的Java框架仍然可用,你在Kotlin中编写的任何框架都很容易被那些依然顽固的死守在Java阵线的朋友们所采纳。

1# 熟悉Kotlin的语法

Kotlin不像那些在学术界出生的奇怪的语言。其语法对于任何熟练面向对象编程(OOP)的程序员来说都是熟悉的,可以从或多或少的了解并开始使用。当然与Java有些差异,如reworked constructors或者像val和var这样的变量声明方式。下面的代码段展示了 Konlin 大部分的基础语法:

class
Foo {
    val b: String = "b"     // val 表示固定值
    var i: Int =0          // var 表示变量
    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}")  //  4 加 7 和为 11

3# 类型判断

Kotlin会推测你输入的变量类型,提高了可读性:

**val**
a = "abc"                        // 推断变量类型为字符串
val b = 4                        // 推断变量类型为 Int
val c: Double = 0.7              // 这里明确的指定变量类型
val d: List<String> = ArrayList()     // 同样明确的指明变量类型

4# 智能类型转换

如果可能的话, Kotlin编译器会跟从您的逻辑然后 自动转换类型,这意味着再不用通过 instanceof 明确检查转换后的类型:

if (obj is String) {
    print(obj.toUpperCase())    // 现在 obj 是一个字符串
}

5# 更直观的等号

您可以停止显式地调用equals(),因为== 运算符现在能检查结构相等性:

val john1 = Person("John")
val john2 = Person("John")

john1 == john2    //true  (结构性相等)
john1 === john2   // false(引用性等于)

6# 默认参数

不需要通过使用不同的参数来定义类似的方法:

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

7# 参数命名

结合默认参数,参数命名消除了对 构建器的需要 :

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

8# 使用When 表达式

做多个条件判断时 ,switch被替换为更可读和灵活的when表达式 :

when
(x) {
    1 -> 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 行为可以添加到公共字段中,这意味着可以通过消除无意义的getter和 setter 防止我们的代码过于臃肿 。

class Frame
{
    var width: Int = 800
    var height: Int = 600

    val pixels: Int
        get() = width * height
}

10 # Data 类

这是一个POJO(Plain Old Java Object),他会自动包含toString()equals()hashCode() copy()方法,与Java不同,它不会占用太多行代码:

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# 解构声明

一些对象可以被解构,这对于迭代 maps 是有用的:

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.format(): String {
    return this.replace(' ', '_')
}
val formatted = str.format()

标准库扩展的Java原生类型的功能,也是String特别需要的:

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

15# Null 安全性

或许我们可以把Java称之为最静态的语言。对它而言 ,一个String类型的变量不能保证一定引用为String - 它可能引用为 null 。即使我们习惯了这一点,但这确实会引起静态类型检查的安全性问题,因此Java程序员在开发过程中总是会担心所谓的NPEs(NullPointerException)

Kotlin通过区分 非空类型可空类型 来解决这个问题 。默认情况下,类型为非空。但是可以像这样通过添加一个来使其可空:

var a: String = "abc"
a = null               //编译错误

var b: String? = "xyz"
b = null               // 没问题

当您访问可空类型时,Kotlin会强制您防范NPEs:

val x = b.length       // 编译错误:b可能为null

虽然这可能看起来很麻烦,但由于这些功能,会大大减少出错几率。我们仍然可以使用智能类型转换,尽可能将可空类型转换为非空值:

if (b == null) return
val x = b.length       // 没问题

我们还可以使用安全调用?. ,它使变量可空,而不是抛出NPE:

val x= b?.length       // x 是一个可空的 int 类型

安全调用可以结合在一起,以避免我们有时像在其他语言编写的嵌套那样的繁琐的if-not-null检查,如果我们想要一个默认值,而不是 null,我们可以使用 elvis 运算符“?:”:

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

如果上面没有一个适用于你,而你需要一个NPE,您只能明确要求:

val x = b?.length ?: throw NullPointerException()  // 与下面一样
val x = b!!.length                                 // 与上述相同

16# 更好的Lambdas

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(Domain-specificlanguage) 的理想选择 。参考 Anko 作为DSL,旨在增强Android开发的一个例子:

verticalLayout
{
    padding = dip(30)
    editText {
        hint = "Name"
        textSize = 24f
    }
    editText {
        hint = "Password"
        textSize = 24f
    }
    button("Login") {
        textSize = 26f
    }
}

17# IDE 支持

如果你打算开始使用 Kotlin,有多种不同 IDE可供你选择。但是我强烈建议您使用与Kotlin 紧密捆绑在一起IntelliJ ,它展示了使用同一人设计语言和IDE的优势。

只是给你举一个小而聪明的例子,当我第一次尝试从Stack Overflow中复制粘贴一些Java代码时,这个东西弹出来了: IntelliJ了解如果你想把Java代码粘贴到Kotlin文件中


原文地址:Why you should totally switch to kotlin