IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android学习笔记-Kotlin -> 正文阅读

[移动开发]Android学习笔记-Kotlin

持续更新~~~~



1 Kotlin快速入门

01 运行kotlin项目

??可以百度kotlin代码在线运行网站。

??可以在Android studio 新建kotlin文件直接运行(前提是在Android studio建立的kotlin版本项目下)
在这里插入图片描述

2 编程之本:变量和函数

01 变量

??只允许在变量前声明两种关键字:val和var。

  • val(value的简写)用来声明一个不可变的变量,这种变量在初始赋值之后就再也不能重新赋值,对应Java中的final变量
  • var(variable的简写)用来声明一个可变的变量,这种变量在初始赋值之后仍然可以再被重新赋值,对应Java中的非final变量

??Kotlin完全抛弃了Java中的基本数据类型,全部使用了对象数据类型。
显示声明变量类型

val a:Int = 10
Java基本数据类型Kotlin对象数据类型数据类型说明
intInt整型
longLong长整型
shortShort短整型
floatFloat单精度浮点型
doubleDouble双精度浮点型
booleanBoolean布尔型
charChar字符型
byteByte字节型

02函数

fun methodName(param1: Int, param2: Int): Int {
	return 0
}

??参数的声明格式是“参数名: 参数类型”,其中参数名也是可以随便定义的,这一点和函数名类似。如果不想接收任何参数,那么写一对空括号就可以了。
??参数括号后面的那部分是可选的,用于声明该函数会返回什么类型的数据,上述示例就表示该函数会返回一个Int类型的数据。如果你的函数不需要返回任何数据,这部分可以直接不写。
例子:

fun largerNumber(num1 : Int,num2 : Int){
    return max(num1,num2)
}
fun main() {
    val a = 37
    val b = 21
    val value = largerNumber(a,b)
    println(value)
}

在这里插入图片描述

3 程序逻辑控制

01 if语句

fun largerNumber(num1 : Int,num2 : Int){
	var value = 0
	if (num1 > num2) {
		value = num1
	} else {
		value = num2
	}
	return value
}

简化:

fun largerNumber(num1: Int, num2: Int): Int {
	return if (num1 > num2) {
		num1
	} else {
		num2
	}
}

语法糖简化(当一个函数只有一行代码时,可以省略函数体部分,直接将这一行代码使用等号串连在函数定义的尾部。)

fun largerNumber(num1: Int, num2: Int) 
= 
if (num1 > num2) {
	num1
} else {
	num2
}

语法糖再简化

fun largerNumber(num1: Int, num2: Int) = if (num1 > num2) num1 else num2

02 when语句

有点类似java中的switch

fun getScore(name: String) = when (name) {
    "Tom" -> 86
    "Jim" -> 77
    "Jack" -> 95
    "Lily" -> 100
    else -> 0
}

格式: 匹配值 -> { 执行逻辑 } (当执行逻辑只有一句话时,可以省略{})

除了精确匹配之外,when语句还允许进行类型匹配

fun checkNumber(num: Number) {
    when (num) {
        is Int -> println("number is Int")
        is Double -> println("number is Double")
        else -> println("number not support")
    }
}

03 循环语句

val range = 0..10
//val range = 0 until 10
//val range = 10 downTo 0
for (i in range){
    println(i)
}

??其中
0…10相当于[0,10]
0 until 10 相当于[0,10)
10 downTo 0 相当于 [10,0]

4 面向对象编程

01 类与对象

定义一个类:

class Person {
    var name = ""
    var age = 0
    fun eat(){
        println(name + " is eating. He is " + age + " years old")
    }
}

new 对象

fun main(){
    var p = Person()
    p.name = "lee"
    p.age = 18
    p.eat()
}

在这里插入图片描述

02 继承和构造函数

令Person类可以被继承

//添加open
open class Person {
	...
}

Student继承Person

1.
//每个类默认都会有一个不带参数的主构造函数,
//当然你也可以显式地给它指明参数。
//主构造函数的特点是没有函数体,直接定义在类名的后面即可。
class Student : Person() {
    var sno = ""
    var grade = 0
    //重写tostring方法
    override fun toString(): String {
        return "Student(sno='$sno', grade=$grade)"
    }
}

//实例化
var stu = Student()
stu.age = 18
stu.name = "lee"
stu.grade = 4
stu.sno = "2017051313"

2.主构造函数的特点是没有函数体,直接定义在类名的后面即可
class Student(val sno: String, val grade: Int) : Person() {
}

//在这里,Person类后面的一对空括号表示Student类的主构造函数在初始化的时候会
//调用Person类的无参数构造函数,即使在无参数的情况下,这对括号也不能省略
//实例化
var stu = Student("2017051313",4)

当父类的主构造函数不为空时

//我们可以在Student类的主构造函数中加上name和age这两个参数,
//再将这两个参数传给Person类的构造函数
class Student(val sno: String, val grade: Int, name: String, age: Int) :
	Person(name, age) {
...
}

次构造函数
当一个类既有主构造函数又有次构造函数时,所有的次构造函数都必须调用主构造函数(包括间接调用)。

class Student(val sno: String, val grade: Int, name: String, age: Int) :
        Person(name, age) {
    constructor(name: String, age: Int) : this("", 0, name, age) {
    }
    constructor() : this("", 0) {
    }
}

//此时有3种方式实例化
val student1 = Student()
val student2 = Student("Jack", 19)
val student3 = Student("a123", 5, "Jack", 19)

03 接口

子类继承父类、实现接口

//父类
open class Person(val name:String, val age:Int) {

}
//接口
interface Study {
    fun readBooks()
    fun doHomework()
}
//子类继承父类、实现接口,都用":",实用","隔开
class Student(name:String,age: Int):Person(name,age),Study{
    override fun readBooks(){
        println(name + " is readBooks")
    }

    override fun doHomework() {
        println(name + " is doHomework")
    }

}

实例化

fun main() {
    //1
    var stu = Student("lee",18)
    stu.doHomework()
    stu.readBooks()

    //2
    doStudy(stu)
}
fun doStudy(study: Study) {
    study.readBooks()
    study.doHomework()
}

结果:
在这里插入图片描述
??Kotlin还增加了一个额外的功能:允许对接口中定义的函数进行默认实现(在实现类中,可以不实现该函数了)

函数的可见性修饰符

修饰符JavaKotlin
public所有类可见所有类可见(默认)
private当前类可见当前类可见
protected当前类、子类、同一包路径下的类可见当前类、子类可见
default同一包路径下的类可见(默认)
internal同一模块中的类可见

04 数据类与单例类

??数据类通常需要重写equals()、hashCode()、toString()这几个方法。
其中,

  • equals()方法用于判断两个数据类是否相等。
  • hashCode()方法作为equals()的配套方法,也需要一起重写,否则会导致HashMap、HashSet等hash相关的系统类无法正常工作。
  • toString()方法用于提供更清晰的输入日志,否则一个数据类默认打印出来的就是一行内存地址。

??根据实际需求编写equal和hashcode函数的内容.

java中需要重写方法,kotlin中只需要"data"关键字
数据类Cellphone

data class Cellphone(val brand: String, val price: Double)

调用

fun main() {
    var cellphone = Cellphone("OPPO",3000.0)
    println(cellphone)
}

在这里插入图片描述
单例类
??只需要将class改成object即可

object Singleton {
    fun singletonTest(){
        println("singletonTest is called")
    }
}

调用

Singleton.singletonTest()

在这里插入图片描述

5 Lambda编程

??传统意义上的集合主要就是List和Set,再广泛一点的话,像Map这样的键值对数据结构也可以包含进来。
List、Set和Map在Java中都是接口.

  • List的主要实现类是ArrayList和LinkedList
  • Set的主要实现类是HashSet
  • Map的主要实现类是HashMap

01 集合的创建与遍历

??对于list,有两种生成方法,其中listOf生成的list集合,内容不可变

fun main() {
    val list = listOf<String>("apple","banana","orange") //集合内容不可变
    val mutableList = mutableListOf<String>("apple","banana","orange") //集合内容可以变
    mutableList.add("grape")
    for (fruit in mutableList){
        println(fruit)
    }
}

??对于set,有两种生成方法,跟list类似,只是改成setOf和mutableSetOf.并且set不能放重复元素,放,也只会保存一个

??Kotlin中并不建议使用put()和get()方法来对Map进行添加和读取数据操作,而是更加推荐使用一种类似于数组下标的语法结构

val map = HashMap<String, Int>()
map["Apple"] = 1
map["Banana"] = 2
map["Orange"] = 3
map["Pear"] = 4
map["Grape"] = 5
//更加简便的方法
val map = mapOf("Apple" to 1, "Banana" to 2, "Orange" to 3, "Pear" to 4, "Grape" to 5)

//遍历map
for ((fruit, number) in map) {
	println("fruit is " + fruit + ", number is " + number)
}

02 集合的函数式API

总结:
??在大括号内填写条件.

//获得字符串长度最长的那个词
    val list = listOf<String>("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
    val maxLengthFruit = list.maxByOrNull { it.length }
    println("max length fruit is " + maxLengthFruit)

??Lambda表达式的语法结构:
??{参数名1: 参数类型, 参数名2: 参数类型 -> 函数体}
首先最外层是一对大括号,
如果有参数传入到Lambda表达式中的话,我们还需要声明参数列表,
参数列表的结尾使用一个->符号,表示参数列表的结束以及函数体的开始, 函数体中可以编写任意行代码(虽然不建议编写太长的代码),并且最后一行代码会自动作为Lambda表达式的返回值

??maxBy就是一个普通的函数而已,只不过它接收的是一个Lambda类型的参数,并且会在遍历集合时将每次遍历的值作为参数传递给Lambda表达式。
??maxBy函数的工作原理是根据我们传入的条件来遍历集合,从而找到该条件下的最大值

val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
val lambda = { fruit: String -> fruit.length }
val maxLengthFruit = list.maxByOrNull(lambda)

?简化

val maxLengthFruit = list.maxByOrNull({ fruit: String -> fruit.length })

?1 .Kotlin规定,当Lambda参数是函数的最后一个参数时,可以将Lambda表达式移到函数括号的外面

val maxLengthFruit = list.maxByOrNull(){ fruit: String -> fruit.length }

?2. 如果Lambda参数是函数的唯一一个参数的话,还可以将函数的括号省略:

val maxLengthFruit = list.maxByOrNull{ fruit: String -> fruit.length }

?3. Lambda表达式中的参数列表其实在大多数情况下不必声明参数类型

val maxLengthFruit = list.maxByOrNull{ fruit -> fruit.length }

?4. 当Lambda表达式的参数列表中只有一个参数时,也不必声明参数名,而是可以使用it关键字来代替

val maxLengthFruit = list.maxByOrNull { it.length }

??集合中的map函数是最常用的一种函数式API,它用于将集合中的每个元素都映射成一个另外的值,映射的规则在Lambda表达式中指定,最终生成一个新的集合。
??filter函数是用来过滤集合中的数据的,它可以单独使用,也可以配合刚才的map函数一起使用。

val list = listOf<String>("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")

val newList = list.filter { it.length <= 5 }.map { it.toUpperCase() }
for (fruit in newList){
    println(fruit)
}

在这里插入图片描述
??any函数用于判断集合中是否至少存在一个元素满足指定条件,all函数用于判断集合中是否所有元素都满足指定条件。

val list = listOf<String>("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")

val anyResult = list.any { it.length <= 5 }
val allResult = list.all { it.length <= 5 }
println("anyResult is " + anyResult + ", allResult is " + allResult)

在这里插入图片描述

03 Java函数式API的使用

总结:
??对作为参数的 单抽象方法接口(参数) 进行简化
??Kotlin代码中调用了一个Java方法,并且该方法接收一个Java单抽象方法接口参数,就可以使用函数式API。
格式:

//其中new Thread是构造方法,是java方法;  Runnable是单抽象方法接口,并作为构造方法的参数
new Thread(new Runnable() {
	@Override
	public void run() {
		System.out.println("Thread is running");
	}
}).start();

简化:

  1. kotlin写法
Thread(object :Runnable{
    override fun run() {
        println("run")
    }
}).start()
  1. 因为Runnable类中只有一个待实现方法,即使这里没有显式地重写run()方法,Kotlin也能自动明白Runnable后面的Lambda表达式就是要在run()方法中实现的内容。
Thread(Runnable {
    println("run")
}).start()
  1. 继续省略,kotlin知道参数是Runnable,省略Runnable.移动括号,省略括号.
Thread{
    println("run")
}.start()

实例:

btn.setOnClickListener{
	println("click")
}

6 空指针检查

??Android系统上崩溃率最高的异常类型就是空指针异常(NullPointerException)。

fun doStudy(study: Study) {
	study.readBooks()
	study.doHomework()
}

??在kotlin中,如果调用方法传入null值,会报错
在这里插入图片描述

01 可空类型系统

??只需在类后面添加"?",并进行判空即可

fun doStudy(study: Study?) {
    if (study != null) {
        study.readBooks()
        study.doHomework()
    }
}

在这里插入图片描述

02 判空辅助工具

??

"?."操作符.

当对象不为空时正常调用相应的方法,
当对象为空时则什么都不做。

//优化
fun doStudy(study: Study?) {
	study?.readBooks()
	study?.doHomework()
}

"?:"操作符

操作符的左右两边都接收一个表达式
如果左边表达式的结果不为空就返回左边表达式的结果,否则就返回右边表达式的结果。

val c = if (a ! = null) {
	a
} else {
	b
}

简化:

val c = a ?: b

非空断言(确信不会为空,自己负责后果)

在这里插入图片描述
非空断言

fun printUpperCase() {
    val upperCase = content!!.toUpperCase()
    println(upperCase)
}

let函数

??这个函数提供了函数式API的编程接口,并将原始调用对象作为参数传递到Lambda表达式中。

obj.let { obj2 ->
// 编写具体的业务逻辑
}

具体实例:

fun doStudy(study: Study?) {
	study?.readBooks()
	study?.doHomework()
}
//用了let
fun doStudy(study: Study?) {
    study?.let { stu ->
        stu.readBooks()
        stu.doHomework()
    }
}

let函数是可以处理全局变量的判空问题的,而if判断语句则无法做到这一点。
在这里插入图片描述

全局变量,其他线程可能对study变量进行修改,导致空指针风险

7 Kotlin中的小魔术

01 字符串内嵌表达式

格式:

" hello, ${object.name}" //当大括号内表达式只有一个变量时,可以将大括号省略.

实例:

open class Person(val name:String, val age:Int) {

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

在这里插入图片描述

02 默认值

//默认参数str = "hello".调用该方法,不传第二个参数时的默认值
fun printParams(num: Int, str: String = "hello") {
    println("num is $num , str is $str")
}
fun main() {
    printParams(123)
}

若默认值在前边,则使用键值对传值

fun printParams(num: Int = 100, str: String) {
    println("num is $num , str is $str")
}
fun main() {
    printParams(str = "world")
}

默认值代替次构造函数

class Student(val sno: String, val grade: Int, name: String, age: Int) :
    Person(name, age) {
    constructor(name: String, age: Int) : this("", 0, name, age) {
    }
    constructor() : this("", 0) {
    }
}

//代替
class Student(val sno: String = "", val grade: Int = 0, name: String = "", age: Int = 0) :
    Person(name, age) {
}

8

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-19 12:09:56  更:2021-08-19 12:10:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/30 22:38:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码