前言
最近在学kotlin,之所以想写这篇文章,是因为自己就有这个疑问,总不能蒙着头就开始学,自己之前一直用Java进行Android开发,到底Kotlin相比Java,优势在哪里?像我这种菜鸡,到底应该把时间花在深入学习Java还是开始学习Kotlin?最后得出的结论是都需要。
概述
其实这个问题,Google官方也早已有回答。Google Android Studio 的技术负责人 Jeffrey van Gogh 表示,这个问题在 Google 发出的“Android 应用程序开发应该优先使用 Kotlin”,英文原文“Android development would become 'Kotlin-first'”的这份声明中被提出来了。从这份声明的标题就可以看出,Google鼓励Android开发者优先使用Kotlin,当然Google在很多方面将继续支持Java,这两者对于Android开发来说可以说是无缝连接。以下是Google对Kotlin和Java的支持方面的一些差异:
语法上的优势
这篇文章先从语法层面探究Kotlin相比与Java的优势,或者说不同点,毕竟语法是最直观的感受。每个特性选取了代表性的、令我印象深刻的例子记录了下来。完整的Kotlin语法教程可以参考Kotlin官网。
简洁、高效
Kotlin语法舍弃了不必要的成分,写起来非常简洁、高效。
(1)舍弃了句末的分号
(2)实例化对象时不需要new关键字
var person: Person = Person()
(3)is取代instanceof
if (content is String) {...}
(4)区间
// 输出"1234"
for (i in 1..4) print(i)
// 倒序,输出"4321"
for (i in 4 downTo 1) print(i)
// 指定步长为2,输出"13"
for (i in 1..4 step 2) print(i)
// 指定步长为2,倒序,输出"42"
for (i in 4 downTo 1 step 2) print(i)
(5)变量与常量定义
// 变量定义
var x: Int = 1
var x = 5 // 系统自动推断变量类型为Int
// 常量定义
val a: Int = 1
val b = 1 // 系统自动推断变量类型为Int
val c: Int // 如果不在声明时初始化则必须提供变量类型
c = 1 // 赋值
(6)函数定义
fun sum(a: Int, b: Int): Int { // Int类型参数,Int类型返回值
return a + b
}
(7)when取代switch
when (x) {
1 -> print("x = 1")
2 -> print("x = 2")
else -> { // 相当于switch的default
print("x != 1 && x != 2")
}
}
安全
Kotlin的空安全设计是一大亮点,主要包括使用 ? 以及 !! 对空值进行处理。
// 类型后面加?表示可为空
var numStr: String? = "1"
// numStr为空则抛出空指针异常
val num = numStr!!.toInt()
// numStr为空则不做处理返回 null
val num = numStr?.toInt()
// numStr为空返回0
val num = numStr?.toInt() ?: 0
类操作的优化
除了上面说到的优势或者说特性外,Kotlin对类的操作也是区分于Java的一大方面。
(1)类构造方法
Kotlin中类构造方法有主次之分,一个类可以包含一个主构造方法和多个次构造方法。
其中,主构造方法中不能包含任何代码,初始化代码可以放在初始化代码段中,初始化代码段使用 init 关键字作为前缀。
class Person constructor(firstName: String) {
init {
println("FirstName is $firstName")
}
}
如果主构造器有注解,或者有可见度修饰符,这时constructor关键字是必须的,注解和修饰符要放在它之前。否则可以省略。
次构造方法必须加constructor关键字,而且如果有主构造方法,次构造方法必须直接或间接(通过另一个次构造方法)代理主构造方法。方式是使用this关键字:
class Person(val name: String) {
constructor (name: String, age:Int) : this(name) {
// 初始化...
}
}
(2)与Java相反,Kotlin的类默认是不可继承的,如果需要继承某个类,则需将该类修饰为open:
open class Super(p: Int) // 父类
class Sub(p: Int) : Super(p) // 子类
(3)数据类
数据类也是Kotlin相对Java的一项重大改进,只需通过data关键字声明一个数据类:
data class User(val name: String, val age: Int)
Kotlin会自动帮你实现数据类所需的操作,如getter/setter,equals(),hashCode(),copy()等函数。
(4)伴随对象
一个类一般需要一些静态的属性和方法,让这个类的所有对象共享,这时候就可以使用伴随对象。
class TestClass {
companion object Factory {
fun newInstance(): TestClass = TestClass ()
}
}
val instance = TestClass.newInstance()
函数式编程
函数式编程是区分于面向对象编程的另一种编程理念,Kotlin语言正是这种理念的体现。说实话当我刚了解到这一点时我的感受是震撼的,毕竟在我这种菜鸡的眼里,面向对象就是王道,更接近于真实世界,更易于理解。但存在即合理,既然Kotlin选择了函数式编程,而且应用也越来越广泛,自然有它的优势在。于是,键盘一响,我开始了流利的操作:“什么是函数式编程”、“函数式编程与面向对象编程”.....嘿嘿。
函数式编程(英语:functional programming)或称函数程序设计,又称泛函编程,是一种编程范型,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数编程语言最重要的基础是λ演算(lambda calculus)。而且λ演算的函数可以接受函数当作输入(引数)和输出(传出值)。
面向对象的优点众所周知,灵活性、可维护性、可扩展性等等,但同时面向对象也存在缺点:在面向对象编程中,数据是可变的,因此在多线程并发编程中数据的准确性很难保证。这是普遍的说法,我个人理解的话,也不是说难以保证,但需要花一些操作或者代价去保证这一点是肯定的。
而对于函数式编程,这一点却不需要担心:
在函数式编程中,由于数据全部都是不可变的,所以没有并发编程的问题,是多线程安全的。可以有效降低程序运行中所产生的副作用,对于快速迭代的项目来说,函数式编程可以实现函数与函数之间的热切换而不用担心数据的问题,因为它是以函数作为最小单位的,只要函数与函数之间的关系正确即可保证结果的正确性。 函数式编程的表达方式更加符合人类日常生活中的语法,代码可读性更强。实现同样的功能函数式编程所需要的代码比面向对象编程要少很多,代码更加简洁明晰。使用函数式编程开发的速度也比用面向对象要高很多。
但是,我愚钝的脑袋想了想,如果变量不可变,那....其实,在函数式编程里,有另外的措施:用函数去返回一个复制的新对象,在这个新的对象里,改变你想改的那个值。原来如此。
但是我想了想,又想不明白了,那为什么在Kotlin的代码里,还是可以见到改变一个变量值的代码呢,是因为Kotlin既支持函数式编程,又支持面向对象,只是说Kotlin的设计理念,或者说Kotlin鼓励大家去进行函数式编程,个人理解。
在函数式编程中,函数具有最重要的地位,最直接的体现是lambda表达式:
val add = {a : Int , b : Int -> a + b}
这样的一个对象,与函数无异。而且,有了这样的表达式,函数也可以作为方法中的参数了:
fun test(a : Int , b : (num1 : Int , num2 : Int) -> Int) : Int{
return a + b.invoke(3,5)
}
// 调用
test(10,{ num1: Int, num2: Int -> num1 + num2 }) // 结果为:18
这就是高阶函数,这里不详细探究语法,不多说,举这个例子只是为了说明,在函数式编程中,一切皆函数。
lambda表达式在Android中的应用:
// 普通写法
mBtn.setOnClickListener(object : View.OnClickListener{
override fun onClick(v: View?) {
Toast.makeText(this,"onClick",Toast.LENGTH_SHORT).show()
}
})
// lambda表达式
mBtn.setOnClickListener { Toast.makeText(this,"onClick",Toast.LENGTH_SHORT).show() }
个人感受
作为一名Android开发者,Kotlin漫漫学习路,对于习惯了Java的我来说,变化还是挺大的,特别是第一次看到?和!!这些符号,脑子里全是?,无聊之际记录记录,不写下来总感觉学了等于没学,学了也记不住,还是太菜...
最后
为了让大家更好的去学习和提升自己,我和几位大佬一起收录整理的 Flutter进阶资料以及Android学习PDF+架构视频+面试文档+源码笔记 ,并且还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料……
这些都是我闲暇时还会反复翻阅的精品资料。可以有效的帮助大家掌握知识、理解原理。当然你也可以拿去查漏补缺,提升自身的竞争力。
如果你有需要的话,可以前往 GitHub 自行查阅。