为什么要用Kotlin代替Java

简介: 为什么要用Kotlin代替Java

我想告诉你一个名为Kotlin的新编程语言,以及为什么你应该为你的下一个项目考虑它。我曾经更喜欢Java,但去年我发现自己只要能够编写Kotlin,在这一点上我真的想不出Java会是一个更好的选择。


它是由JetBrains开发的,事实上这些是IDE套件背后的人,比如IntelliJ和ReSharper, 在Kotlin中真的很闪亮。它实用而简洁,使编码成为令人满意和高效的体验。

虽然Kotlin编译了JavaScript和很快的机器代码,但我将专注于它的主要环境,即JVM。

所以这里有几个原因你应该完全切换到Kotlin(没有特别的顺序):


0 # Java互操作性


Kotlin与Java可以100%互操作。使用Kotlin的时候我们可以继续使用老的Java库。你喜欢用的java第三方框架在kotlin项目中仍然可用,而且用kotlin写的框架同样可以用在Java项目中


1# 熟悉的语法


Kotlin并不是学术界的奇怪语言。任何来自面向对象编程的程序员都熟悉它的语法,并且可以从一开始就或多或少地理解它。当然,与Java有一些不同之处,例如重写的构造函数或val var变量声明。下面的代码段介绍了大部分基础知识

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# 字符串插值

就好像String.format(),在Kotlin中内置了一个更智能,更易读的字符串格式化功能

val x = 4
val y =7
print("$x 和$y的总和是$(x+y)") // 4 和7的总和是11

3# 类型推断

Kotlin会在您认为可以提高可读性的地方推断您的类型:

val a =“abc”//类型推断为String 
val b = 4 //类型推断为Int 
val c:Double = 0.7 //明确声明类型
val d:List <String> = ArrayList()//明确声明类型
• 1
• 2
• 3
• 4

4# 智能类型转换

如果可能,Kotlin编译器会跟踪您的逻辑和自动转换类型。这意味着您不用在做instanceof判断之后做显示的类型转换

if(obj is String){
    print(obj.toUpperCase())//这里不用做显示类型转换
}
• 1
• 2
• 3

5# == 和 ===

== 等效于java中的equals(),=== 等效于java中的 ==

val john1 = Person("John")
val john2 = Person("John")
john1 == john2    // true  (structural equality)
john1 === john2   // false (referential equality)
• 1
• 2
• 3
• 4

6# 默认参数

方法有多个不同参数版本的时候,不需要定义多个重载函数

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

7#命名参数

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

build("PacMan", 400, 300)                           // equivalent
build(title = "PacMan", width = 400, height = 300)  // equivalent
build(width = 400, height = 300, title = "PacMan")  // equivalent
• 1
• 2
• 3

8# When 表达式

使用when表达式代替switch

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 -> println("x is out of range")
}
• 1
• 2
• 3
• 4
• 5
• 6
• 7

而且when表达式可以赋值给变量

val res: Boolean = when {
    obj == null -> false
    obj is String -> true
    else -> throw IllegalStateException()
}
• 1
• 2
• 3
• 4
• 5

9# 属性

自定义的set和get方法可以添加到public字段,这意味着我们可以通过隐式的getter和setter来避免臃肿的代码

class Frame{
    var width: Int = 800
    var height: Int =600
    val pixels: Int
    get () = width*height
}
• 1
• 2
• 3
• 4
• 5
• 6

10# 数据类

使用java编写一个POJO,需要重写getter和setter,toString,equals等方法,在Kotlin中实现类似的功能十分简洁

data Persron(val name: String,var email: String,var age: Int)
val john = Person("John","john@gmail.com",24)
• 1
• 2

11# 运算符重载

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

data 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)
• 1
• 2
• 3
• 4

12# 解构声明

一些对象可以被解构,特别是在遍历map的时候有用

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

13# 范围

可读性秒杀java

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) { ... }
• 1
• 2
• 3
• 4
• 5

14# 扩展函数

还记得你第一次使用java给List排序吗?在List中你找不到sort方法。然后你不得不通过google学习Collections.sort()。

如果只有一种方法可以向旧类添加新函数; 这样您的IDE可以帮助您在代码完成中找到正确的功能。在Kotlin你可以做到这一点:

fun String.replaceSpaces(): String { 
return this.replace('','_')
} 
val formatted = str.replaceSpaces()
• 1
• 2
• 3
• 4
• 5

15# 空指针安全

在java中如果一个引用指向null,在使用该引用时可能会抛出NullPointException。在Kotlin中将引用分为两种非空类型和可空类型。默认的就是非空类型,可空类型在类型后面添加?

var a: String = "abc"//默认非空类型
a = null //编译报错
var b:String? = "xyz"//可空类型
b = null //没问题
• 1
• 2
• 3
• 4
• 5

无论何时访问可空类型,Kotlin都会强制您防范NPE:

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

虽然这看起来很麻烦,但由于它的一些功能,它真的很轻松。我们仍然有智能强制转换,它会尽可能地将可空类型转换为非null:

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

我们也可以使用安全调用?.,其值为null而不是抛出NPE

val x = b?.length // x的类型是可以为空的Int
• 1
• 2

安全调用可以链接在一起,以避免我们有时用其他语言编写的嵌套if-not-null检查,如果我们想要一个默认值,null我们可以使用elvis运算符?::

val name = ship?.captain?.name?:“unknown”
• 1
• 2

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

val x = b?.length?:throw NullPointerException()//与下面相同
val x = b!!.length //与上面相同
• 1
• 2

16# 更好的Lambdas

在可读性和简洁性之间完美平衡,这得益于一些聪明的设计选择。语法首先是直截了当的

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

这里有聪明的一点:

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

这些事实相结合,使以下三行等效:

numbers.filter({x  - > x.isPrime()})
numbers.filter {x  - > x.isPrime()} 
numbers.filter {it.isPrime()}
• 1
• 2
• 3
• 4

这使我们能够编写简洁的功能代码

persons
    .filter {it.age> = 18} 
    .sortedBy {it.name} 
    .map {it.email} 
    .forEach {print(it)}
相关文章
|
11天前
|
Java 开发工具 Android开发
Kotlin语法笔记(26) -Kotlin 与 Java 共存(1)
本系列教程笔记详细讲解了Kotlin语法,适合需要深入了解Kotlin的开发者。若需快速学习Kotlin,建议查看“简洁”系列教程。本期重点介绍了Kotlin与Java的共存方式,包括属性、单例对象、默认参数方法、包方法、扩展方法以及内部类和成员的互操作性。通过这些内容,帮助你在项目中更好地结合使用这两种语言。
26 1
|
2天前
|
安全 Java 编译器
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
Kotlin教程笔记(27) -Kotlin 与 Java 共存(二)
|
2天前
|
Java 开发工具 Android开发
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
Kotlin教程笔记(26) -Kotlin 与 Java 共存(一)
|
2天前
|
Java 编译器 Android开发
Kotlin教程笔记(28) -Kotlin 与 Java 混编
Kotlin教程笔记(28) -Kotlin 与 Java 混编
|
8天前
|
安全 Java Android开发
Kotlin为什么没有Java流行
Kotlin流行不起来的原因
35 1
|
11天前
|
Java 编译器 Android开发
Kotlin语法笔记(28) -Kotlin 与 Java 混编
本系列教程详细讲解了Kotlin语法,适合需要深入了解Kotlin的开发者。对于希望快速学习Kotlin的用户,推荐查看“简洁”系列教程。本文档重点介绍了Kotlin与Java混编的技巧,包括代码转换、类调用、ProGuard问题、Android library开发建议以及在Kotlin和Java之间互相调用的方法。
13 1
|
11天前
|
安全 Java 编译器
Kotlin语法笔记(27) -Kotlin 与 Java 共存(二)
本教程详细讲解Kotlin语法,适合希望深入了解Kotlin的开发者。若需快速入门,建议查阅“简洁”系列教程。本文重点探讨Kotlin与Java共存的高级话题,包括属性访问、空安全、泛型处理、同步机制及SAM转换等,助你在项目中逐步引入Kotlin。
13 1
|
12天前
|
Java 编译器 Android开发
Kotlin语法笔记(28) -Kotlin 与 Java 混编
Kotlin语法笔记(28) -Kotlin 与 Java 混编
17 2
|
8天前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
79 38
|
5天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?