Kotlin简介
2011年7月,JetBrains推出Kotlin项目,这是一个面向JVM的新语言
2012年2月,JetBrains以Apache 2许可证开源此项目。
2016年2月15日,Kotlin v1.0发布,这被认为是第一个官方稳定版本。
在Google I/O 2017中,Google宣布在Android上为Kotlin提供最佳支持,取代java成为官方开发语言。
函数和变量
kotlin中的函数和变量可以直接声明在文件中
使用fun关键字声明函数
使用var关键字声明变量,可读可写变量
使用val关键字声明只读变量,不可修改,相当于java中的final
创建对象,只需调用构造器即可,不需要java中的new关键字
            
            
              kotlin
              
              
            
          
          fun main(){
  var age:Int =18
}
fun doubleNumber(x:Int):Int{
  return x*2
}声明一个数组,使用arrayOf关键字:
            
            
              kt
              
              
            
          
          private val studyList = arrayOf("语文","数学","英语")静态函数
比如工具类中常用的dp2px()
- 直接写在Util.kt文件中
            
            
              kt
              
              
            
          
          private val displayMetrics = Resources.getSystem().displayMetrics
fun dp2px(dp:Float):Float{
  return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,displayMetrics)
}那么在kotlin中调用的时候直接dp2px(15f)即可。在java中调用使用Utilkt.dp2px(15f),需要在文件名后边加上kt后缀
- 使用object关键字声明
            
            
              kt
              
              
            
          
          object Util{
  private val displayMetrics = Resources.getSystem().displayMetrics
  fun dp2px(dp:Float):Float{
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,displayMetrics)
  }
}在kotlin中调用Util.dp2px(15f),在java中调用Util.INSTANCE.dp2px(15f)
使用object关键字声明,相当于创建了一个类的单例对象
- 使用companion关键字 伴生对象
 比如application:
            
            
              kt
              
              
            
          
          class BaseApplication : Application(){
  companion object{
   private lateinit var currentApplication: Context
   fun currentApplication():Context{
     retun currentApplication
   }
  }
  override fun onCreate(){
    super.onCreate()
    currentApplication = this
  }
}在kotlin中调用BaseApplication.currentApplication(),然后在java中调用BaseApplication.Companion.currentApplication()
类
依然使用class关键字声明一个类:
            
            
              kt
              
              
            
          
          class User{
  var name:String?=null
  //set,get方法要紧跟成员变量,且里边要使用field关键字
  //set,get方法默认可以不写
  set(value){
    field = value
  }
  get(){
    field
  }
  constructor(){}
  constructor(name: String?){
    this.name = name
  }
}继承和实现接口只需要一个冒号:,不同的是继承的类需要加上一个括号()。
            
            
              kt
              
              
            
          
          class MainActivity:AppcompatActivity(),View.OnClickListener{
  ...
}但是需要注意的是,如果在类中显式声明了构造器,就不能加上这个括号()
在调用父类的构造器或者本类中其他构造器都要使用:,比如
            
            
              kt
              
              
            
          
          class MyView : View {
  constructor(context:Context):this(context,null){
  }
  constructor(context:Context, attr:AttributeSet?):super(context,attr){
  }
}另外,对一个类成员的set,get方法的访问,可以直接使用.成员变量名的方式:
            
            
              kt
              
              
            
          
          user.name = "xxxxxx" //进行赋值,相当于调用了setName()方法如果是在java中去调用,不能使用user.name,只能使用其set,get方法。但是如果使用某一个成员变量,需要在kotlin中声明这个变量的时候,使用@JvmField注解
            
            
              kt
              
              
            
          
          @JvmField
var name:String?=null匿名内部类
创建一个一个匿名内部类,需要object关键字
比如:
            
            
              kt
              
              
            
          
          call.enqueue(object:Callback){
  override fun onResponse(call:Call, response:Response){}
  override fun onFailure(call:Call, e:IOException)
}另外在内部类中使用外部类的成员变量,在java中为Class.this.xx,在kotlin中要使用this@Class.xx
静态内部类
- 静态内部类可以直接在一个类中使用class声明一个内部类,这个类可以使用伴生对象
- 如果要使用普通的嵌套内部类,则需要inner class去修饰
 另外internal关键字可以去修饰类和方法,表示当前module可见,别的module不可见
接口和抽象类,枚举类
接口(interface xxx)和抽象类(abstract class xxx)的声明,与java中相同
但是枚举类不一样:
            
            
              kt
              
              
            
          
          class SdutyList{
    enum class Type{
         MATH{...}
    }
}kotlin中的类默认都是被final关键字修饰的,不能被继承,方法不能被重写,如果想要一个类可以被继承,需要使用abstract关键字修饰,方法需要使用open修饰,才可以重写。
判断语句
if 和 when:
            
            
              kt
              
              
            
          
          if(code in 100..199){}  //表示code是否在100到199,双闭区间另外使用when关键字,相当于java中的switch
            
            
              kt
              
              
            
          
          when (code){//这里可以支持表达式
     in 100..199->{}
     in 200..299->{}
     else->{}
}遍历和循环
遍历
除了常规的for遍历一个数组或者集合
            
            
              kt
              
              
            
          
          //比如有一个`users`的集合
var passUsers = ArrayList<User>()
for(user in users){
     if(user.age >= 18){
        passUsers.add(user)
     }
}
可以使用kotlin提供的操作符去简化上述代码:
//使用forEach操作符
users.forEach({user:User->
    if(user.age >= 18){
        passUsers.add(user)
    }
})
//如果forEach()中接收的参数只是一个lambda表达式,可以将{}提到括号外边,且括号可以省略:
users.forEach{user:User->
    if(user.age>=18){
        passUsers.add(user)
    }
}
//另外,也可以使用类型推断,不用声明user的类型
users.forEach{user->
    if(user.age>=18){
        passUsers.add(user)
    }
}
//最后如果一个lambda表达式,只有一个参数,那么这个参数可以省略不写,而会有一个默认的隐式参数it:User
users.forEach{
    if(it.age>=18){
        passUsers.add(it)
    }
}还有,这个例子中相当于过滤一些user,只要符合条件的user,那么可以使用filter操作符来简化:
            
            
              kt
              
              
            
          
          //这里直接过滤出年龄大于等于18的用户
passUsers.add(users.filter{ it.age >= 18 })循环
- 使用repeat关键字
            
            
              kt
              
              
            
          
          //注意这里是一个隐式参数`it:Int`
repeat(100){
    println(it)
}- for-i循环
            
            
              kt
              
              
            
          
          for(i in 0..99){
   println(i)
}集合
- 使用库函数listOf<>()或者mapOf<>()
- 使用对象
            
            
              kt
              
              
            
          
          var studyList:List<Lesson> = ArrayList();
var map:Map<Int, String> = HashMap()但是需要注意的是上面所创建的集合元素都是不可修改的,无法进行增删
所以如果需要元素可变,一般使用:
- arrayListOf<>(),mutableListOf<>(),mutableMapOf<>(),hashMapOf<>()
- var studyList:ArrayList<Lesson> = new ArrayList()
kotlin中的类系统
| Java | Kotlin | 
|---|---|
| Object | Any | 
| void | Unit | 
kotlin中基本数据类型
| Kotlin基本数据类型 | 位宽度 | 
|---|---|
| Char | (字符型) | 
| Boolean | (布尔类型) | 
| Byte | 8(字节型) | 
| Short | 16(短整型) | 
| Int | 32(整型) | 
| Long | 64(长整型) | 
| Float | 32(浮点型) | 
| Double | 64(双精度浮点型) | 
变量的可空控制
kotlin中将变量分为可空和不可空两种类型。
            
            
              kt
              
              
            
          
          //这里的user是一个不可空类型,如果赋值为null,则会报错
var user:User 
//这里的user是一个可空类型,需要加一个问号?
var user:User?=null;那么如果想要调用一个可空类型的变量,有两种方式
            
            
              kt
              
              
            
          
          user!!.getName()   //表示强制调用,不管是否为null
user?.getName()   //表示安全调用,如果不为null,才调用虽然这里可以避免空指针,但是user为null肯定是有问题的,希望在编写代码的时候早发现这些问题。
一个错误的示例:
            
            
              kt
              
              
            
          
          fun a(name:String){
    ...
}
a(user?.getName()!!)