Kotlin基础知识

语言基类
JavaObject
KotlinAny

Aoko库

项目gradle
buildscript {
    ……
    ext.anko_version = "0.10.8" //AnKo库的版本号
}
--------------------------------------------------------
模块gradle
dependencies {
    ……
    implementation "org.jetbrains.anko:anko-common:$anko_version"
}

一些关键字

lateinit ,延时加载,不支持基本类型,不支持val,属性用的时候再初始化
如果想让val支持延时加载且不支持var

val a: String by lazy { "111" }

as ,强转

by,代理

with、apply、let、run、also

1.with

1.在with里可直接调函数
2.最后一个函数的返回值类型就是with的返回值类型

        var s: String = ""
        s.equals("111")
        s.compareTo("123")
        
        val with: Int = with(s) {
            equals("111")
            compareTo("123")
        }

2.apply

和with差不多,但是返回本对象类型

        val apply: String = s.apply {
            equals("111")
            compareTo("123")
        }

3.let(有it)

1.可以判空,如果为空则不会执行

        var s2: String? = null
        s2?.let {
            Log.w("wei", "${111}")
        }

2.最后一个函数的返回值类型就是let的返回值类型

        val let: Boolean = s.let {
            0
            equals("111")
        }

4.run

最后一个函数的返回值类型就是run的返回值类型

        val run:Boolean = s.run {
            0
            compareTo("123")
            equals("111")
        }

5.also

只返回本对象类型

        val also:String = s.also {
            0
            equals("111")
        }

Kotlin基本类型、数组及容器

1.基本类型

开头字母大写即可

2.数组

Kotlin的基本数组类型数组类型名称数组类型的初始化方法
整型数组IntArrayintArrayOf
长整型数组LongArraylongArrayOf
浮点数组FloatArrayfloatArrayOf
双精度数组DoubleArraydoubleArrayOf
布尔型数组BooleanArraybooleanArrayOf
字符数组CharArraycharArrayOf
var array: IntArray = intArrayOf(1, 2, 3)
        array[0]
        array.get(0)
        array.set(0, 5)
        array.size        //Java使用length,Kotlin使用size

也可以指定类型

var stringArray: Array<String> = arrayOf("aa", "cc")

3.容器

与Java类似,Kotlin也有三类基本的容器,集合Set,队列List,映射Map
如果想要进行增加或删除,需要加上前缀Mutable
Kotlin的容器名称初始化方法
只读集合SetsetOf
只读队列ListlistOf
只读映射MapmapOf
可变集合MutableSetmutableSetOf
可变队列MutableListmutableListOf
可变映射MutableMapmutableMapOf
        var list: MutableList<String> = mutableListOf()
        list.add("111")
        list.add("222")
        list.add("333")
        list.remove("111")
        list.removeAt(0)

循环

        for (i in 0 until list.size) {
            Log.w("wei", list[i])
        }
        list.forEach {
            Log.i("wei", it)
        }
        for (i in list.indices) {
            Log.w("wei", list[i])
        }
        for (i in list) {
            Log.w("wei", i)
        }

        step指定步长  downTo表示递减 out@跳出循环
        out@ for (i in 100 downTo 0 step 2) {
            Log.w("wei", list[i])
            out@ break
        }

Map也是有了改变,to 和 Pair 都可以实现初始化

        var map: MutableMap<String, String> = mutableMapOf("4" to "44", "5" to "55", Pair("6", "66"))
        map["1"] = "11" //都是添加 map.put("1","11")
        map["2"] = "22"
        map["3"] = "33"
        map.remove("1")

Kotlin校验字符串空值的几个方法

方法作用
isNullOrEmpty为空指针或者字符串长度为 0 时返回true,非空串与可空串均可调用
isNullOrBlank为空指针、字符串长度为 0 或者全为空格时返回true,非空串与可空串均可调用
isEmpty字符串长度为 0 时返回true,只有非空串可调用
isBlank字符串长度为 0 或者全为空格时返回true,只有非空串可调用
isNotEmpty字符串长度 >0 返回true,只有非空串可调用
isNotBlank字符串长度 >0 且不是全空格串时返回true,只有非空串可调用

操作符

var string: String? = null      声明变量实例时,在类型名称后面加 ? 表示该变量可空
string?.length                  调用变量方法时,在变量名称后面加 ? 表示一旦变量为空就返回null
string?.length ?: 10            新引入运算 ?: ,表示一旦变量为空  返回该运算符右边的表达式
string!!.length                 新引入运算 !! ,通知编译器不做非空校验。如果运行时发现变量为空就扔出异常

结构相等

字符串的等值性判断要求Java的判断方式Kotlin的判断方式
判断两个字符串是否相等str1.equals(str2)str1 == str2
判断两个字符串是否不等!str1.equals(str2)str1 != str2

引用相等

意思是除了值相等以外,还需要引用的地址(即存储地址)也必须相等(使用 ===/!== 判断)

  1. 对于基本类型,包括整型、浮点型、布尔型、字符串,结构相等和引用相等没有区别
  2. 同一个类声明的不同变量,只要有一个属性不等,则其既是结构不等,也是引用不等
  3. 同一个类声明的不同变量,若equals方法校验的每个属性都相等(如通过clone方法克隆出来的变量复制品),则其结构相等,但引用不等

函数运用

1.泛型函数

    /**
     * 泛型函数
     * 
     * vararg也就是Java中的Object...object
     */
    fun <T> t(a: String, vararg other: T): Unit {
        for (item in other) {
            Log.w(a, "${item.toString()}")
        }
    }

2.简化函数

fun add(a: Int = 1, b: Int = 3) = a + b

3.内联函数

fun setArrayNumber(array: Array<Number>) {}
inline fun <reified T : Number> setArrayNumber(array: Array<T>) {}
var intArray:Array<Int> = arrayOf(1,2,3)
        setArrayNumber(intArray)
调用如上第一个方法走不通
inline  可以看成是一种替换,编译后setArrayNumber(intArray) 会被第二种方法体替换掉
reified 相当于继承关系

4.尾递归函数

指的是函数末尾的返回值重复调用了自身函数。此时要在fun前面加上关键字tailrec,告诉编译器这是一个尾递归函数,编译器则会进行相应的优化,从而提高程序性能

5.高阶函数

把一个函数指定为另一个函数的入口参数,也就是函数作为参数传递给另一个函数

    fun method(a: Int, b: Int, greater: (Int, Int) -> Int): Int {
        return greater(a, b)
    }
//1
method(2, 3) { a, b -> a + b }
//2
method(2, 3, { a, b -> a - b })

6.拓展函数

    fun String.exspand() {}
var str: String = ""
        str.exspand()

在外部对String做了一个拓展
你想要拓展的类型.任意名

单例模式

添加object即可
object XXXUtils {
    fun test() {

    }
}

类的构造函数

Kotlin把函数看成是一种特殊的变量,那么类在某种意义上算是一种特殊的函数。所以构造函数的输入参数得直接加到类名后面,而init方法仅仅表示创建类实例时的初始化动作。

//如果主构造函数没有带@符号的注解说明,类名后面的constructor可以省略
class MyBean constructor(name: String, age: Int) {

    init {
        Log.w("wei", "MyBean  init")
    }
    
    //重构造必须继承主构造,在有了主构造参数基础上可以自定义其他参数,可以看成是重载
    constructor(name: String, age: Int, birthday: String) : this(name, age) {

    }

    constructor(name: String, age: Int, birthday: String, hobby: String) : this(name, age) {

    }

}

如果主构造有默认参数,如何在Java里省略

//加上@JvmOverloads即可
class MyBean @JvmOverloads constructor(name: String = "wei", age: Int) {
	
}

在主构造参数前面加上 varval 就会变成成员属性
var 能 get 和 set
val 只能 get

class MyBean @JvmOverloads constructor(var name: String, val age: Int) {

    init {
        this.name = "wei"
    }

    override fun toString(): String {
        return "MyBean(name='$name', age=$age)"
    }

}

伴生对象(Java的static)

Java中,静态成员使用 static 关键字来修饰,且外部是通过"类名.静态成员名称"的形式访问静态成员(包括静态属性和静态方法)的。
然而Kotlin取消了关键字static,为了弥补功能缺陷,Kotlin引入了伴生对象的概念。

class MyBean @JvmOverloads constructor(var name: String, val age: Int) {
	……
	//companion object后可不加名称
    companion object MyBeanCompanion {
        var name: String = ""
    }

}

相当于是static

MyBean.MyBeanCompanion.name
MyBean.name

开放性修饰符

修饰符说明
public对所有人开放。Kotlin的类、函数、变量不加开放性修饰符的话,默认是public
internal只对本模块内部开放,这是Kotlin新增的关键字。对于App开发来说,本模块是指App自身
protected只对自己和子类开放
private只对自己开放,即私有

类的继承

要被继承的类

class MyBean @JvmOverloads constructor(var name: String = "wei", val age: Int) {

}

MyBean2不能继承MyBean有两个问题
1.MyBean有主构造函数
2.MyBean没有open修饰符(Kotlin的类默认不能被继承)
在这里插入图片描述
解决第一个问题,注意,正常继承的类后面也要有()

class MyBean2(name: String, age: Int) : MyBean(name, age) {

}

解决第二个问题,被继承类加上open修饰符

open class MyBean @JvmOverloads constructor(var name: String = "wei", val age: Int) {

}
另外只有添加了 open 的函数才能被子类重写,open不能与private一起用(报错且自相矛盾)

接口

在Kotlin中定义接口需要注意以下几点:
1.接口不能定义构造函数,否则编译器会报错
2.接口的内部方法通常要被实现它的类进行重写,所以这些方法默认为抽象类型
3.与Java不同的是,Kotlin允许在接口內部实现某个方法,而1.8之前Java接口的所有内部方法都 必须是抽象方法
4.如果接口中定义了一个属性,实现接口的类必须也重写这个属性

 interface CallBack {

    var status: Boolean

}

这样

class MyBean2(override var status: Boolean) :CallBack{

}

这样

class MyBean2 :CallBack{
    
    override var status: Boolean
        get() = true
        set(value) {}

}

或者这样

class MyBean2 :CallBack{

    override var status: Boolean = true

}

嵌套类和内部类

和Java唯一的区别就是调不到外部类的成员变量

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    //嵌套类
    class A {
        
    }
    
}

而嵌套类加上inner关键字就可变成内部类,同时可以访问外部类成员变量

class MainActivity : AppCompatActivity() {

    var name: String = "wei"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    //内部类
    inner class A {
        fun a() {
            name
        }
    }
    
}

枚举类

加上enum关键字即可

enum class Day {
    Day6,Day7
}

枚举类也存在构造函数

enum class Day( val theName: String) {
    Day6("星期六"), Day7("星期天")
}

获取信息

val theName = Day.Day7.theName

通过ordinal获取下标

val index = Day.Day7.ordinal

密封类

密封类就像是一种更加严格的枚举类,它内部有且仅有自身的实例对象,所以是一个有限的自身实例集合。或者说,密封类采用了嵌套类的手段,它的嵌套类全部由自身派生而来。定义密封的时候,需要在该类的class前面加上关键字sealed作为标记。

有了密封类,外部使用when语句便无须指定 else分支了!

sealed class Day {
    //密封类的每个嵌套类都必须继承该类
    class Day6(var theName: String) : Day()

    class Day7(var theName: String) : Day()
}

    fun eval(day: Day) =
        when (day) {
            is Day.Day6 -> day.theName
            is Day.Day7 -> day.theName
        }

注意,密封的类无法实例化。

        var day:Day = Day.Day7("星期天")
        eval(day)

数据类

在class前面增加关键字data,并声明拥有完整输入参数的构造函数,即可无缝实现以下功能:
1.自动声明与构造函数入参同名的属性字段
2.自动实现每个属性字段的get/set方法
3.自动提供equals()方法,用于比较两个数据对象是否相等
4.自动提供copy方法,允许完整复制某个数据对象,也可在复制后单独修改某几个字段的值
5.自动提供toString方法,用于打印数据对象中保存的所有字段值

数据类必须有主构造函数,且至少有一个输入参数
要声明与输入参数同名的属性,即输入参数前面添加关键字var/val
数据类不能是基类也不能是子类,不能是抽象类,也不能是内部类,更不能是密封类

data class UserBean(var username: String, var password: String) {

    data class Bean(var age: Int)
    
}

模板类

class MyBean4<T>(name: T, age: T) {

    fun method(a: T, b: T) {

    }
}
var myBean4: MyBean4<String> = MyBean4("", "")

序列化传值(Parcelable)

主构造添加属性,实现Parcelable后重写方法,不用你自己敲,放心

class MyMessage(var a: String?, var b: Int) : Parcelable {
    constructor(parcel: Parcel) : this(
        parcel.readString(),
        parcel.readInt()
    )

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(a)
        parcel.writeInt(b)
    }

    override fun describeContents(): Int {
        return 0
    }

    override fun toString(): String {
        return "MyMessage(a=$a, b=$b)"
    }

    companion object CREATOR : Parcelable.Creator<MyMessage> {
        override fun createFromParcel(parcel: Parcel): MyMessage {
            return MyMessage(parcel)
        }

        override fun newArray(size: Int): Array<MyMessage?> {
            return arrayOfNulls(size)
        }
    }

}

放心,Kotlin中还有更简单的方式
主构造添加属性,实现Parcelable,再加上@Parcelize注解,简单的令人发指:)

@Parcelize
class MyMessage2(var a: String, var v: Int) : Parcelable {
    
}

接下来就是跳转传值,还记得Map初始化里的 toPair 吗?

var myMessage: MyMessage = MyMessage("IU", 1993)
startActivity<Main2Activity>("a" to myMessage,Pair("b","bb"))

跳转+传参+启动模式 这就是Anko库带来的便捷

startActivity(intentFor<Main2Activity>("name" to "wei").singleTop())

获取值

val bundle = intent.extras
val myMessage2 = bundle!!.getParcelable<MyMessage2>("a")

若想正常编译,得打开一个扩展,写上面时开关没设置…
在模块的build.gradle

    androidExtensions {
        experimental = true
    }

提示框

提醒对话框(AlertDialog)

anko库的使用让kotlin更简洁

            alert("未来可期", "提示") {
                negativeButton("取消") { }
                positiveButton("确定") { toast("未来可期") }
            }.show()

效果
在这里插入图片描述

下拉框(Spinner)

val listMonth: List<String> = listOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12")
selector("请选择月份", listMonth) { dialogInterface, i -> toast("${listMonth[i]}") }

效果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值