kotlin入门

基本类型、变量、空安全

官方文档

Type Size (bits) Min value Max value
Byte 8 -128 127
Short 16 -32768 32767
Int 32 -2,147,483,648 (-231) 2,147,483,647 (231 - 1)
Long 64 -9,223,372,036,854,775,808 (-263) 9,223,372,036,854,775,807 (263 - 1)
Float 32    
Double 64    

kotlin变量的使用,kotlin的基本数据类型都是引用类型,和java的String一样都是对象

不可变变量,相当于java的final修饰,申明时候必须初始化

使用原型:val 变量名:类型 = 变量值
使用举例:

val valInt = 1  
val valInt2:Int = 2  

valInt不指定类型,会根据赋值自动推导。val定义的变量作为常量存在,其值不可改变。

可变变量、不为null,申明时候必须初始化

使用原型:var 变量名:类型 = 变量值
使用举例

var valLong: Long = 12222  
valLong = 2  

var申明的变量可以改变其值,但是未申明可以为null,赋值null会报错。

可变变量、可为null,通过问号标记

使用原型:var 变量名:类型? = 变量值
使用举例

var varNullString: String?  
varNullString = null
varNullString = "sss"

空安全

当对象或者变量使用问好修饰后,编译器会强制强制要求进行空安全检查,尽可能避免运行时出现空指针异常。空检查时候,如果被检查对象为null,此行代码不会执行

//定义一个可空变量
var varNullString: String? 

//第一种使用方式,建议使用这种
var len = test?.length  
//类似java中
//if(test!=null){
//    len=test.length
//}

 //第二种使用方式  
 len = test!!.length    //这种当test为null时会报异常
//类似java中
//if (test != null) {
//    len = test.length
//} else {
//    抛出异常
//}  

//第三种使用方式
len = test?.length ?: 10  
//类似java中
//if(test!=null){
//   len = test.length
//}else{
//   len = 10;
//}

 

类与继承、接口

官方文档
类、接口、继承、实现接口和java非常类似

类与java区别:

1、kotlin的类中字段默认时public,对外可见,修改控制访问权限时可以设置为private、protect等。
2、kotlin的类中字段默认全部实现get、set方法,需要修改这两个方法时候可以重写
3、kotlin的类可以重写init方法,此方法在类实例化时候调用,可以做初始化操作

接口与java区别

1、kotlin的接口和java有点区别可以定义包含方法体的方法,java的接口只能定义抽象方法。
2、kotlin接口可以定义变量,和接口中的方法一样,类实现接口时必须重写字段。

可见性

可见性官方文档

关键字 可见范围
public 任何看到声明类的客户都会看到其public成员
private 表示仅在此类中可见(包括其所有成员)
protected 与private子类中的+可见相同
internal 模块内可见

继承、实现

kotlin和java一样,只能单继承,可以实现多个接口

原型

class 类名{

}
或者
class 类名:接口1,接口2,接口3,父类{

}

使用举例

定义父类ClassParent,open关键字修饰后才可以被继承

open class ClassParent(data: String) {
    /**
     * 父类中字段
     */
    var dataParent: String? = data
}

定义一个接口InterfaceParent

interface InterfaceParent {
    /**
     * 抽象字段
     */
    var dataInterface: String

    /**
     * 接口中的抽象方法,实现接口后必须重写
     */
    fun setData(data: Int)

    /**
     * 接口中带方法体的方法
     */
    fun setData2(data: Int) {
        //接口中的方法可以有方法体
    }
}

ClassA实现接口InterfaceParent、继承父类ClassParent

class ClassA : ClassParent, InterfaceParent {
    var dataA: Int? = null

    /**
     * 接口中的抽象字段,实现接口时候必须重写
     */
    override var dataInterface: String = ""

    /**
     * 类的初始化块
     */
    init {
        dataInterface = "类的初始化块"
    }

    /**
     * 父类有一个带参数的构造方法,子类必须重写
     */
    constructor(data: String) : super(data) {

    }

    /**
     * 多参数构造方法
     */
    constructor(data: String, dataA: Int?) : super(data) {
        this.dataA = dataA
    }

    /**
     * 重写InterfaceParent中方法
     */
    override fun setData(data: Int) {
        dataA = data
    }
}

 

方法

kotlin中方法概念和java相同,方法原型和java不同,功能比java强大,支持函数作为参数和返回值(高阶函数)

普通方法

方法原型
fun 方法名(参数1:参数类型,参数2:参数类型):返回值类型{

//实现功能

}
使用举例

无参无返回

/**
 * 定义一个无参方法打印data的值
 * 方法返回值是void
 */
fun printData() {
    Log.i(log, "data=$data")
}

有参有返回值

/**
 * 定义参数为String、Boolean的方法
 * 方法返回值是Boolean
 */
fun printData(d: String, b: Boolean): Boolean {
    data = d
    this.b = b
    Log.i(log, "data=$data   ;  b=${this.b}")
    return b
}

参数默认值方法

方法定义时候参数设置默认值,调用方法时候有默认值的参数可以不传递,kotlin自动使用默认值
使用举例
定义方法reformat,normalizeCase、upperCaseFirstLetter默认为true,divideByCamelHumps默认false

fun reformat(
    str: String,
    normalizeCase: Boolean = true,
    upperCaseFirstLetter: Boolean = true,
    divideByCamelHumps: Boolean = false
) {
   //实现功能
}

使用reformat方法

reformat("")
reformat("", false)
reformat("", false, upperCaseFirstLetter = false)
reformat("", false, upperCaseFirstLetter = false, divideByCamelHumps = false)

方法原型
使用举例

高阶函数(详见底部高阶函数介绍)

 

静态方法、变量

官方文档
kotlin静态方法、变量类似java中public static final修饰的变量、方法,使用companion object包裹即可,常量需要const修饰

companion object {
   //放置静态方法、变量
}

使用举例
定义一个类

class StaticData {
    companion object {
        //常量需要const修饰
        const val staticVal = "类似于java的public static final "
        var staticVar = ""
        fun setStaticData(data: String) {
            staticVar = data
        }
    }
}

使用静态常量、方法

val temp = StaticData.staticVal
StaticData.staticVar = temp
StaticData.setStaticData(temp)  

控制流

官方文档

if使用

与java中if类似使用

// Traditional usage 
var max = a 
if (a < b) max = b

// With else 
var max: Int
if (a > b) {
    max = a
} else {
    max = b
}

// As expression 
val max = if (a > b) a else b

for使用

与java的for类似使用,功能略强
collection为定义的集合,step count为循环步进,默认为1

for (item in collection step count){ 
    print(item)
}

在1-3之间遍历,步进为1

for (i in 1..3) {
    println(i)
}

在1-6之间遍历,步进为2

for (i in 6 downTo 0 step 2) {
    println(i)
}

when使用

类似java的switc,功能比switch强大,case条件可以时常量、集合、表达式、类型,when条件可以时一个表达式

val list = ArrayList()
var data = 1
when (data) {
    1 -> {
        //等于1
    }
    2 -> {
        //等于2
    }
    in 3..5 -> {
        //在3-5之间
    }
    in list -> {
        //在list集合中
     }
     !in 6..7 -> {
        //不在6-7之间
     }
     is Int -> {
        //类型为Int时候
     }
     else -> {
        //其它,default
     }
 }  

 

协程

官方文档
百度百科定义协程:
协程不是进程或线程,其执行过程更类似于子例程,或者说不带返回值的函数调用。一个程序可以包含多个协程,可以对比与一个进程包含多个线程,因而下面我们来比较协程和线程。我们知道多个线程相对独立,有自己的上下文,切换受系统控制;而协程也相对独立,有自己的上下文,但是其切换由自己控制,由当前协程切换到其他协程由当前协程来控制。
需要单独依赖库

api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinx_coroutines"  

通过GlobalScope使用,Dispatchers定义协程执行在什么线程,可选IO、MAIN、Default,耗时操作一般在IO线程执行,kotlin通过线程池管理IO线程;刷新界面使用MAIN,默认在调用处所在线程时使用Default。GlobalScope.launch执行时候会有一个返回值,调用返回值中的
join方法可以让主协程或者线程卡在join处,直到子协程执行完成;
cancel方法取消协程;
cancelAndJoin方法取消并等待子协程

    GlobalScope.launch(Dispatchers.IO) {

    }

使用举例
1、开启子线程执行任务

GlobalScope.launch(Dispatchers.IO) {
    //这里是在子线程
    //延迟500毫秒
    delay(500)
    Log.i(log, "这里是协程1,Thread id=${Thread.currentThread().id}")
}  

2、子线程执行,结果返回主线程

GlobalScope.launch(Dispatchers.Main) {
    val job = GlobalScope.launch(Dispatchers.IO) {
        //这里是在子线程
        delay(2000)
        Log.i(log, "这里是IO协程,Thread id=${Thread.currentThread().id}")
    }
    //这里是在UI线程
    //主协程会阻塞在这里,直到子协程执行完成
    job.join()
    //取消任务
    //job.cancel()
    //取消job并且等待它完成
    //job.cancelAndJoin()
    Log.i(log, "这里是Main协程,Thread id=${Thread.currentThread().id}")
}

3、定时任务

GlobalScope.launch(Dispatchers.IO) {
    repeat(10) { i ->
        //这里是在子线程,10此重复时,每次的线程可能不相同
        Log.i(log, "I'm repeat $i ...,Thread id=${Thread.currentThread().id}")
        delay(100)
    }
}  

高阶函数

高阶函数简单理解就是函数的参数或者返回值是函数的函数
原型
fun hight(a:funA,b:funB):funC{

}
使用举例
普通2个普通函数,返回Int类型数据,kotlin中函数的定义可以和变量一样使用val定义

private val data1 = fun(): Int {
    return 10
}

private val data2 = fun(): Int {
    return 2
}

将函数用作一个函数的返回值的高阶函数

fun getData2(): () -> Int {
    return data2
}

定义高阶函数higherFunction

/**
 * 
 * @param aFun  一个无参数,返回值类型为Int的函数类型
 * @param cFun  一个无参数,返回值类型为Int的函数类型
 * @param bFun  一个有两个Int类型参数,返回值类型为Int的函数;类型
 * @return Int类型
 */
private fun higherFunction(
    aFun: () -> Int,
    cFun: () -> Int,
    bFun: (a: () -> Int, b: () -> Int) -> Int
): Int {
    //将参数a、c传入到参数b(函数),得到结果
    return bFun.invoke(aFun, cFun)
}

定义高阶函数higherFunctionAdd

/**
 * 高阶函数higherFunctionAdd、higherFunctionSubtract、higherFunctionMult
 * @param aFun 一个无参数,返回值类型为Int的函数
 * @param bFun 一个无参数,返回值类型为Int的函数
 * @return Int类型
 */
private val higherFunctionAdd = fun(aFun: () -> Int, bFun: () -> Int): Int {
    //调用函数aFun、bFun
    return aFun.invoke() + bFun.invoke()
}

定义高阶函数higherFunctionSubtract

private val higherFunctionSubtract = fun(aFun: () -> Int, bFun: () -> Int): Int {
    //调用函数aFun、bFun
    return aFun.invoke() - bFun.invoke()
}  

定义高阶函数higherFunctionMult

private val higherFunctionMult = fun(aFun: () -> Int, bFun: () -> Int): Int {
    //调用函数aFun、bFun
    return aFun.invoke() * bFun.invoke()
}

使用高阶函数

//使用高阶函数higherFunction,实际是data1 + data2 ,(10 + 2)
val res = higherFunction(data1, getData2(), higherFunctionAdd)

//使用高阶函数higherFunction,实际是data1 - data2 ,(10 - 2)
val res2 = higherFunction(data1, getData2(), higherFunctionSubtract)

//使用高阶函数higherFunction,实际是data1 * data2 ,(10 * 2)
val res3 = higherFunction(data1, getData2(), higherFunctionMult)

你可能感兴趣的:(android,kotlin)