kotlin作为一个现代的适用于多平台的静态类型语言越来越受到java开发同学的喜爱,尤其是android开发同学的喜爱,下面从几个方面浅析一下kotlin和java的一些比较。
Optionals:
在java开发中我们经常会遇到一个异常,就是NPE,也就是所谓的nullPointerException,这个异常号称java最大的bug一直让我们java开发非常头疼,大量的if判断后者try cache捕获异常让我们的代码变得很不优雅,但是在kotlin中已经完美的解决了该问题,只需一个问号:?。新接触kotlin的同学获取对该语言中的?有太多的疑惑,所以不敢使用问号,下面简单说一下:
在kolin中,一切都是对象,所有的变量和常量必须有初始值,而且kotlin中没有基本数据类型,全是引用数据类型,也就是说所用的变量都用可能为null,所以当你为一个变量初始化时,一定要有一个初始值,但是你的初始值一旦为null:
你的IDE一定会提示你报错,那正确的写法应该是:
那么该变量i就有可能为null.然后看下面的语句:
var map : HashMap<String,Any> ? = null
//var empty = map!!.isEmpty()
var empty = map?.isEmpty()
//var empty = map?.isEmpty()?:false
首先定义了一个HashMap,初始化为null,这个时候用map调用isEmpty()方法肯定会报错的,这个时候有两种解决办法,第一让它抛出异常,用!!表示,第二用?,表示我知道它有可能为null,但是还是要执行sEmpty()方法,大不了返回值empty也为null,第四条语句为,如果map?.isEmpty()为null,则为empty赋值为false,这就是Elvis表达式。
Stream和Lambdas表达式
java从jdk8开始引入了stream和lambdas表达式,但是开发者这种特性或者说语法糖一直不感冒,当年尤记得我在java代码中使用stream对collection的filter操作后,技术总监对我严厉的批评,说明java和java开发者都是相对保守的。再者在android开发中,虽然在Java 8和9中可以使用stream和lambdas,但在API 24以下的Android SDK中是不可用的,那也只能意味着放弃,但kotlin的出现让这些语法糖冲新在android中得到了发挥。
请看下面三行代码:
var array = arrayListOf(1,2,3,4,5,5,6,7,8,9,0,-1)
var subArray = array.filter ({ item -> item > 0 })
var subArray2 = array.map { it + 10 }
首先定义了一个变量array,类型为ArrayList<Int>,并add了一组数据,这个时候我想要对这个集合做一些操作,比如说筛选,那么在java中最常用的就是for循环或while循环遍历,但是如果使用stream和lambdas表达式就是一行代码搞定,也就是上面的第二行语句。
首先说一下何为stream,其实就是对元素集合统一、快速、并行操作的一种方式,何为lambdas表达式:其实就是一个匿名函数,支持函数式编程,有自己独特的语法糖格式。
然后再看看array.filter()的源码:
/**
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
return filterTo(ArrayList<T>(), predicate)
}
灰常简单,首先参数为一个匿名函数(匿名函数中有一个参数T,返回值为布尔类型),返回值为List<T>。
在看android中的一段代码:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val text = findViewById(R.id.text) as TextView
text.setOnClickListener { v ->
Toast.makeText(this@MainActivity, "Hello", Toast.LENGTH_LONG).show()
v.visibility = View.VISIBLE
}
}
}
当为text设置一个监听时,我们习惯的写法是写一个匿名内部类,但是在kotlin可以用lambdas表达式代替,但是只限于监听接口只有一个方法实现。
Binding of views
这是一个具体的Android问题,Jetbrains为我们提供了Kotlin Android扩展,一个官方的支持库通过一个gradle的插件来简化这个问题(以及其他一些问题)。
构造器
在java中constructor相对kotlin比较灵活,在kotlin中,定义一个class时,也会有一个默认的构造器,当你自定一个构造器时可以分为主构造器和二级构造器:
class Test constructor(name : String){
var name : String ? = null
var age : Int ? = null
constructor(age : Int,name : String) : this(name)
init {
this.name = name
this.age = age
}
}
但是,如果类有主构造函数,每个二级构造函数都要,或直接或间接通过另一个二级构造函数代理主构造函数。在同一个类中代理另一个构造函数使用this 关键字,如上面的代码。
上面的几点是我决得比较有意思的,并在实际开发中会经常的使用,java和kotlin当然还有大量的差异,比如java中的static、this关键字在kotlin中如何实现,java中的.class在kotlin中如何表示等等,这些都需要我们在实际开发中慢慢了解和习惯。