Andriod开发24000字长文带你入门kotlin

2023-06-1419:41:17APP与小程序开发Comments1,207 views字数 17053阅读模式
Andriod开发24000字长文带你入门kotlin

Kotlin 是谷歌大力推广的安卓开发语言,用来取代 java。
因为 java 被甲骨文收购,这个公司肯定会将 java 商业化。这是谷歌推广 kotlin 的初衷。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

kotlin 与 java 虚拟机

Andriod开发24000字长文带你入门kotlin

java 使用 jvm 实现了跨平台,但是 kotlin 的快平台特性比 java 更加强大,它可以直接生成二级制代码运行。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

Andriod开发24000字长文带你入门kotlin

kotlin 的优点

  • 缝合各个语言的优点,下一代的安卓开发语言。
  • kotlin 可以实现全栈开发
Andriod开发24000字长文带你入门kotlin

kotlin 的基本语法

变量与打印

只能说和 ts 一模一样。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    // 打印语句
    println("hello kotlin")
    // 变量赋值
    var name: String = "lijiajun"
    name = "li"
    println(name)
}

console文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

hello kotlin
li
​
进程已结束,退出代码0

内置的数据类型:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

  • String -> 字符串
  • Char -> 单字符
  • Boolean -> 布尔值
  • Int -> 整形
  • Double -> 小数
  • Float -> 小数
  • List -> 集合
  • Set -> 无重复集合
  • Map -> 键值对

在 kotlin 中没有 int ,float 这样的写法,我们的 Int、Float 等等实际上是会被转化成 java 中的 java int 和 java float。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

kotlin中的只读变量

val 关键字。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    // 这个变量永远不会被修改 -> val
    val info: String = "info"
}

kotlin中类型推断

kotlin 会自动推断变量的类型,所以这里的 :String 是多余的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

Andriod开发24000字长文带你入门kotlin

所以上面的代码可以简化:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    // 这个变量永远不会被修改 -> val
    val info = "info"
    println(info)
}

编译时常量

val 是只读的变量,不是常量。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

kotlin 中的常量只能是基本的数据类型。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

const val PI = 3.1415
fun main() {
    // 这个变量永远不会被修改 -> val
    val info = "info"
    println(info)
}

编译时常量只能写在函数的外面,在编译时赋值。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

查看kotlin编译后的字节码

原来的代码:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

const val PI = 3.1415
fun main() {
    // 这个变量永远不会被修改 -> val
    val info = "info"
    println(info)
}

编译后的字节码:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

// ================MainKt.class =================
// class version 52.0 (52)
// access flags 0x31
public final class MainKt {
​
​
  // access flags 0x19
  public final static D PI = 3.1415
​
  // access flags 0x19
  public final static main()V
   L0
    LINENUMBER 4 L0
    LDC "info"
    ASTORE 0
   L1
    LINENUMBER 5 L1
   L2
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ALOAD 0
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
   L3
   L4
    LINENUMBER 6 L4
    RETURN
   L5
    LOCALVARIABLE info Ljava/lang/String; L1 L5 0
    MAXSTACK = 2
    MAXLOCALS = 1
​
  // access flags 0x1009
  public static synthetic main([Ljava/lang/String;)V
    INVOKESTATIC MainKt.main ()V
    RETURN
    MAXSTACK = 0
    MAXLOCALS = 1
​
  @Lkotlin/Metadata;(mv={1, 8, 0}, k=2, d1={"u0000u000enu0000nu0002u0010u0006nu0000nu0002u0010u0002nu0000u001au0006u0010u0002u001au00020u0003"u000eu0010u0000u001au00020u0001Xu0086Tu00a2u0006u0002nu0000u00a8u0006u0004"}, d2={"PI", "", "main", "", "kotlin_learning"})
  // compiled from: Main.kt
}
​
​
// ================META-INF/kotlin_learning.kotlin_module =================
   •   •   •        
​
​
 ••MainKt" * 

因为只有编译之后的字节码才能被 jvm 执行。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

kotlin中的引用类型

像这样的写法:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

val age:Int = 100
val pi:Float = 3.14.15f

实际上这里面的 Int 、Float是 kotlin 中定义的类,也就是引用类型文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

实际上最后会被转换成 java 的基本类型文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

import kotlin.Metadata;

@Metadata(
   mv = {1, 8, 0},
   k = 2,
   d1 = {"u0000u000enu0000nu0002u0010u0006nu0000nu0002u0010u0002nu0000u001au0006u0010u0002u001au00020u0003"u000eu0010u0000u001au00020u0001Xu0086T¢u0006u0002nu0000¨u0006u0004"},
   d2 = {"PI", "", "main", "", "kotlin_learning"}
)
public final class MainKt {
   public static final double PI = 3.1415;

   public static final void main() {
      String info = "info";
      System.out.println(info);
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }
}

所以不用担心代码的性能,但是在转化的时候是肯定的会消耗性能的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

kotlin的range表达式

start..end文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

包含开头结尾。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

import kotlin.random.Random

fun main() {
    val randomInt = Random.nextInt(0, 101)
    if (randomInt in 10..59) {
        println("不及格")
    } else if (randomInt in 60..100) {
        println("及格啦")
    } else {
        println("分数太低了")
    }
}

kotlin中的when表达式

类似于其他语言中的 switch 表达式。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

import kotlin.random.Random

fun main() {
    // if (randomInt in 10..59) {
    //     println("不及格")
    // } else if (randomInt in 60..100) {
    //     println("及格啦")
    // } else {
    //     println("分数太低了")
    // }
    when (Random.nextInt(0, 101)) {
        0 -> println("你考了零蛋")
        in 1..59 -> println("你的成绩不合格")
        in 60..100 -> println("你的成绩合格")
        !in 0..100 -> println("你的成绩有问题")
        else -> println("处理其余的情况")
    }
}

kotlin中的字符串模板

"${name}"文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val age = 123
    println("你今年${age}岁了")
}

还可以在其中使用简单的语句:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

import kotlin.random.Random

fun main() {
    val age = Random.nextInt(0, 200)
    println("你今年${age}岁了")
    println("啊这,${if (age < 100) "你还年轻" else "你太老了"}")
}

console文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

你今年90岁了
啊这,你还年轻

进程已结束,退出代码0

如果在 java 中写的话,就只能使用 + 来拼接字符串了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

kotlin的函数

基本的写法

kotlin 的函数也和 ts 十分相似:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    method(1, "hello")
}

public fun method(age: Int, name: String): Int {
    println("hello func")
    return 1
}

注意此处的 public 实际上是冗余的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

Andriod开发24000字长文带你入门kotlin

默认参数

public fun method(name: String, age: Int = 2): Int {
    println("hello func $age")
    return 10
}

默认的参数写在最后一个。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

具名参数

使用具名参数可以将默认的参数的位置随意放置:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    method(name = "hello")
}

public fun method(age: Int = 2, name: String): Int {
    println("hello func $age")
    return 10
}

Unit函数

就是没有值返回,就像 void 一样。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

默认的话不写也是有的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

private fun method1(): Unit {
    return 1
}

像上面的这种写法就是有问题的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

Nothing类型

其实就是抛出异常文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

private fun show(number: Int) {
    when (number) {
        -1 -> TODO("没有这种分数")
        in 0..59 -> println("您的分数不及格")
        in 60..70 -> println("您的分数及格")
    }
}

TODO:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

@kotlin.internal.InlineOnly
public inline fun TODO(reason: String): Nothing = throw NotImplementedError("An operation is not implemented: $reason")

反引号的使用

  • 用来测试代码
    fun main() {
    `这是登录功能 2023年6月1日`("李嘉俊", "ljj")
    }文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

    private fun `这是登录功能 2023年6月1日`(name: String, pwd: String) {
    println("姓名$name,密码$pwd")
    }

  • 解决在使用 java 中的函数,但是像 in 这种在 java 中并不是关键字的单词,是可以作为函数名的,但是在 kotlin 中,in 是关键字,所以需要使用引号
    JavaFunc.`in`()
  • 为了预防反编译
Andriod开发24000字长文带你入门kotlin

匿名函数Lambda

什么是匿名函数

下面是一个匿名函数的例子:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    println("lijiajun".count())
    var len = "lijiajun".count() {
        it == 'i'
    }
    println(len)
}

console文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

8
2

进程已结束,退出代码0

匿名函数隐式返回

最后一行的值默认就是返回值。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    // 函数输入输出的声明
    val methodAction: () -> String
    // 函数的实现
    methodAction = {
        val temp = 123
        // 最后一行的值就是返回值,不需要写 return
        "lijiajun$temp"
    }
    println(methodAction())
}

上面的函数也可以连接起来写:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    // 函数的实现
    val methodAction: () -> String = {
        val temp = 123
        // 最后一行的值就是返回值,不需要写 return
        "lijiajun$temp"
    }
    println(methodAction())
}

匿名函数的参数

fun main() {
    // 函数的实现
    val methodAction: (Int, String, Double) -> String = { p1, p2, p3 ->
        val temp = 123
        // 最后一行的值就是返回值,不需要写 return
        "lijiajun$temp,$p1,$p2,$p3"
    }
    println(methodAction(1, "whoami", 1.0))
}

it 关键字

我们上面的匿名函数如果只有一个参数的话,我们可以这么写:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    // 函数的实现
    val methodAction: (Int) -> String = { p1 ->
        val temp = 123
        // 最后一行的值就是返回值,不需要写 return
        "lijiajun$temp,$p1"
    }
    println(methodAction(1))
}

但是 kotlin 给我们提供了 it 关键字,我们可以这样写:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    // 函数的实现
    val methodAction: (Int) -> String = {
        val temp = 123
        // 最后一行的值就是返回值,不需要写 return
        "lijiajun$temp,$it"
    }
    println(methodAction(1))
}

我们可以借助 idea 的提示来看:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

Andriod开发24000字长文带你入门kotlin

匿名函数的类型推断

就是很多时候我们是不需要手动指定返回值的类型的,kotlin 可以帮我们推断:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    // 函数的实现
    val methodAction = { p1: Int ->
        val temp = 123
        // 最后一行的值就是返回值,不需要写 return
        "lijiajun$temp,$p1"
    }
    println(methodAction(1))
}

lambda表达式

上述所学的匿名函数就是 lambda 表达式。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

Andriod开发24000字长文带你入门kotlin

kotlin 函数进阶

函数当做参数

其实就是将 lambda 表达式作为函数的参数先进行声明,然后在实际使用的时候写上具体的用法。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

import kotlin.math.log
import kotlin.random.Random

fun main() {
    loginApi("lijiajun", "123456") { msg: String, code: Int ->
        println("$msg,$code")
    }
}

// 模拟数据库
const val DATABASE_NAME = "LIJIJUN"
const val DATABASE_PWD = "1223"

// 登录的 api -> 模仿前端的代码
private fun loginApi(username: String, userPwd: String, res: (String, Int) -> Unit) {
    if (username == null || userPwd == null) {
        TODO("用户名或者密码为空")
    }
    // 前端校验
    if (username.length > 3 && userPwd.length > 3) {
        loginApiServer(username, userPwd)
        // 登录成功后进行其他的操作...
        res("login success", 200)
    } else {
        res("login fail", 404)
        TODO("用户名或者密码不合格")
    }
}

private fun loginApiServer(name: String, pwd: String): Boolean {
    return name == DATABASE_NAME && pwd == DATABASE_PWD
}

以上的代码仅供学习,实际上逻辑是有问题的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

lambda 表达式作为参数的另外一种实现

实际上也是可以这没写的,虽然好像更合理,但是不建议。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    loginApi("lijiajun", "123456", { resMsg: String, msgCode: Int ->
        println("$resMsg,$msgCode")
    })
}

和上面的文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    loginApi("lijiajun", "123456") { msg: String, code: Int ->
        println("$msg,$code")
    }
}

是一样的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

函数内联

如果函数使用了 lambda 参数,就需要声明成内联。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

如果不声明内联的话,在调用端会生成多个对象造成性能损耗。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

(在 kotlin 代码中并无法看出,但是在编译后的字节码,然后反编译得到的 java 代码中可以看出,性能损耗)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

添加内联关键字即可 inline文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

private inline fun loginApi(username: String, userPwd: String, res: (String, Int) -> Unit) {
    if (username == null || userPwd == null) {
        TODO("用户名或者密码为空")
    }
    // 前端校验
    if (username.length > 3 && userPwd.length > 3) {
        loginApiServer(username, userPwd)
        // 登录成功后进行其他的操作...
        res("login success", 200)
    } else {
        res("login fail", 404)
        TODO("用户名或者密码不合格")
    }
}

其实就相当于 C++ 中的 #define 宏定义,宏替换。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

函数引用

可以将 lambda 函数的内容提出来。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

形式 ::func文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

可以看出,如果使用了函数引用的话,看起来会更加合理,因为我们根据形式上就可以看出将函数作为第三个参数传入了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

import kotlin.math.log
import kotlin.random.Random

fun main() {
    loginApi("lijiajun", "123456", ::func)
}

private fun func(msgString: String, msgCode: Int) {
    println("$msgString,$msgCode")
}

// 模拟数据库
const val DATABASE_NAME = "LIJIJUN"
const val DATABASE_PWD = "1223"

// 登录的 api -> 模仿前端的代码
private inline fun loginApi(username: String, userPwd: String, res: (String, Int) -> Unit) {
    if (username == null || userPwd == null) {
        TODO("用户名或者密码为空")
    }
    // 前端校验
    if (username.length > 3 && userPwd.length > 3) {
        loginApiServer(username, userPwd)
        // 登录成功后进行其他的操作...
        res("login success", 200)
    } else {
        res("login fail", 404)
        TODO("用户名或者密码不合格")
    }
}

private fun loginApiServer(name: String, pwd: String): Boolean {
    return name == DATABASE_NAME && pwd == DATABASE_PWD
}

将lambda函数作为返回值

fun main() {
    val res = show()
    println(res(22, 100.0))
}

// 我们返回一个 lambda 函数
private fun show(): (Int, Double) -> String {
    val value = "lijiajun"
    return { age: Int, grade: Double ->
        "$value,年龄是$age,成绩是$grade"
    }
}

console文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

lijiajun,年龄是22,成绩是100.0

进程已结束,退出代码0

匿名函数与具名函数

fun main() {
    // 匿名函数
    show("lijiajun", 22, '男', "学习kotlin") { res: String ->
        println(res)
    }
}

private inline fun show(name: String, age: Int, sex: Char, study: String, showRes: (String) -> Unit) {
    val str = "$name,$age,$sex,$study"
    showRes(str)
}

一下的 {} 中的部分就是 lambda 表达式的实现体,我们也叫作匿名函数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

Andriod开发24000字长文带你入门kotlin

而以下的方式就是具名函数,就是将 lambda 表达式的实现体提出来单独写一个函数:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    // 匿名函数
    show("lijiajun", 22, '男', "学习kotlin", ::func1)
}

private fun func1(res: String) {
    println(res)
}

private inline fun show(name: String, age: Int, sex: Char, study: String, showRes: (String) -> Unit) {
    val str = "$name,$age,$sex,$study"
    showRes(str)
}

kotlin 语言的一些特点

kotlin 的可空性

kotlin中的变量除非声明的时候声明了可空,否则不能赋值为null文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

写法就是在原来类型后面加上问号即可。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    var name: String? = "lijiajun"
    name = null
}

kotlin 的安全调用操作符

如果一开始给变量定义了可空,在使用一些 api 的时候就会报错,因为你先要保证变量不为 null 才能使用这个 api,所以需要我们给出补救措施。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

Andriod开发24000字长文带你入门kotlin

补救措施:在变量后面加上表示如果是 null 的话,后面就不执行了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    var name: String? = "lijiajun"
    println(name?.length)
}

kotlin 使用 let 安全调用

在变量的值确定不是 null 之后,使用 let 执行相关的操作。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    var name: String? = "lijiajun"
    name = null
    var r = name?.let {
        // it == name
        it
    }
    println(r)
}

kotlin 非空断言

就是做出补救措施的时候,我们断言它就是不为null,实际上我也不管了,就是必须要执行。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

但实际上写的时候 idea 不会让你出错的。:)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

Andriod开发24000字长文带你入门kotlin

if 对空值的补救

其实就是做一个最简单的判断。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    var name: String? = "lijiajun"
    name = null
    if(name !== null) {
        
    }
}

kotlin 空合并操作符

fun main() {
    var name: String? = "lijiajun"
    name = null
    println(name ?: "您的值为null")
}

console文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

您的值为null

进程已结束,退出代码0

结合let一起使用:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    var name: String? = "lijiajun"
    name = null
    println(name ?: "您的值为null")
    println(name?.let { "$it" } ?: "你的值为null")
}

console文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

您的值为null
你的值为null

进程已结束,退出代码0

kotlin 中的异常处理和自定义异常

使用 try {} catch {} 处理即可。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

kotlin 的先决条件函数

Andriod开发24000字长文带你入门kotlin

kotlin 中常用写法和 api

所有的 api 以下都是简单介绍,具体的使用可以查看官网即可。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

substring

裁剪字符串。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

str.substring(0,index)

indexOf

str.indexOf('char')

until

直到文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

str.substring(0,index)

等价于

str.substring(0 until index)

split

// 根据逗号分割字符串

str.split(",")

结构

val (str1,str2) = str.split(",")

replace

val sourcePwd = "hsadksghashdfiahghiwe"

// 对密码进行加密
// 实际上就是对对应的字符进行替换
// 具体请查看官方文档

fun encryptPassword(password: String): String {
    return password.replace('a', '1')
                   .replace('e', '2')
                   .replace('i', '3')
                   .replace('o', '4')
                   .replace('u', '5')
}

fun decryptPassword(encryptedPassword: String): String {
    return encryptedPassword.replace('1', 'a')
                           .replace('2', 'e')
                           .replace('3', 'i')
                           .replace('4', 'o')
                           .replace('5', 'u')
}

== 和 ===

==: 值的比较文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

===:值和类型的比较文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

注意和 js 中的对比,== 在 js 中是需要先转化再比较的,在 kotlin 中并不会,而是直接比较。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

字符串遍历操作

str.forEach{
    println("$it")
}

关于 for 循环的操作:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

1. for-in循环

for-in循环用于遍历数组、集合或其他可迭代对象。它的语法如下:

```kotlin
for (item in collection) {
    // 循环体
}
```

其中,item是集合中的每个元素,collection是要遍历的集合。例如,我们可以使用for-in循环遍历一个整型数组:

```kotlin
val numbers = intArrayOf(1, 2, 3, 4, 5)

for (number in numbers) {
    println(number)
}
```

输出:

```
1
2
3
4
5
```

2. for循环

for循环用于执行一定次数的循环。它的语法如下:

```kotlin
for (i in start..end step stepSize) {
    // 循环体
}
```

其中,i是循环变量,start是起始值,end是结束值,stepSize是步长。例如,我们可以使用for循环打印出1到10之间的偶数:

```kotlin
for (i in 1..10 step 2) {
    println(i)
}
```

输出:

```
1
3
5
7
9
```

在for循环中,我们还可以使用downTo和until关键字来控制循环的方向和结束条件。例如,我们可以使用downTo关键字打印出10到1之间的数:

```kotlin
for (i in 10 downTo 1) {
    println(i)
}
```

输出:

```
10
9
8
7
6
5
4
3
2
1
```

还可以使用until关键字指定结束值不包含在循环中:

```kotlin
for (i in 0 until 10) {
    println(i)
}
```

输出:

```
0
1
2
3
4
5
6
7
8
9
```

toInt

将其他类型转为 Int,小数去掉文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

"666".toInt()

// 严谨的写法需要判断是否为空,并且使用 toIntOrNull

val num:Int? = "666.6".toIntOrNull()

roundToInt

四舍五入文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

apply

  • 没有 it
  • 有一个 this,就是字符串本身
  • 函数的返回值就是字符串本身

run

  • 函数的返回值的类型就最后一行的值的类型
  • 有一个 this,就是字符串本身

with

also

takeIf

takeUnless

kotlin 数据结构之集合

集合 List

创建集合:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list: List<String> = listOf("lijiajun", "zhangsan", "lisi")
    println(list)
}

根据我们的类型推断,可以简写:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list = listOf("lijiajun", "zhangsan", "lisi")
    println(list)
}

为了防止访问越界:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

使用 getOrElse 解决越界的问题文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list = listOf("lijiajun", "zhangsan", "lisi")
    println(list.getOrElse(4) { "越界" })
}

console文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

越界

进程已结束,退出代码0

使用getOrNull 解决越界问题文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list = listOf("lijiajun", "zhangsan", "lisi")
    println(list.getOrNull(4))
}

console文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

null

进程已结束,退出代码0

结合空合并运算符:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list = listOf("lijiajun", "zhangsan", "lisi")
    println(list.getOrNull(4) ?: "你越界了")
}

我们尽量选择使用 getOrElse文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

可变 List 集合

普通的 List 集合是无法完成有关改变的操作的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

mutableListOf文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list: MutableList<String> = mutableListOf("lijiajun", "zhangsan")
    println(list)
    list.add("lisi")
    println(list)
    list.remove("lijiajun")
    println(list)
}

console文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

[lijiajun, zhangsan]
[lijiajun, zhangsan, lisi]
[zhangsan, lisi]

进程已结束,退出代码0

可以利用 toMutableList 将不可变集合变为可变的集合:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list: List<String> = listOf("zhangsan")
    val list2: MutableList<String> = list.toMutableList()
    list2.remove("zhangsan")
    println(list2)
}

mutator 函数

就是一些关于增加和减少元素的简便操作文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list = mutableListOf<String>("zhangsan")
    list += "lisi"
    list += "wangwu"
    println(list)
    list -= "lisi"
    println(list)
}

console文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

[zhangsan, lisi, wangwu]
[zhangsan, wangwu]

进程已结束,退出代码0

removeIf 函数

条件移出:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

1.删除所有元素文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list = mutableListOf<String>("zhangsan")
    list.removeIf { true }
    println(list)
}

2.删除某一个指定的元素文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list = mutableListOf<String>("zhangsan")
    list.removeIf { item -> item.contains("zhangsan") }
    println(list)
}

遍历集合

使用 for 循环文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list = mutableListOf<String>("zhangsan", "lisi", "wangwu")
    for (i in list) {
        println(i)
    }
}

使用 forEach文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list = mutableListOf<String>("zhangsan", "lisi", "wangwu")
    list.forEach { item ->
        println(item)
    }
}

使用 forEachIndexed(有下标)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list = mutableListOf<String>("zhangsan", "lisi", "wangwu")
    list.forEachIndexed { index, item ->
        println("$index,$item")
    }
}

Set 集合

会自动帮我们去重文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val set: Set<String> = setOf("zhangsan", "lisi", "wangwu", "lisi")
    println(set)
}

set取值的话是不能够通过单纯的下标来取,我们通过 elementAt 来取:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val set: Set<String> = setOf("zhangsan", "lisi", "wangwu", "lisi")
    println(set.elementAt(0))
}

处理越界的方法和 List 都是类似的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

println(set.elementAtOrElse(100) { "越界了" })

kotlin 数据结构之数组

数组的创建和越界访问

所有的数组类型:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

Andriod开发24000字长文带你入门kotlin
fun main() {
    val arr: IntArray = intArrayOf(1, 2)
    println(arr[0])
    println(arr.elementAtOrElse(100) { -1 })
}

集合转数组

to...Array()文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val list: List<String> = listOf("lijiajun", "zhangsan")
    val arr = list.toTypedArray()
    println(arr[0])
}

对象类型数组

val arr: Array<File> = arrayOf(File("123"))

kotlin 数据结构之 Map

创建map

1.直接创建文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val map: Map<String, Int> = mapOf("lijiajun" to 123, "lisi" to 123)
}

2.使用Pair文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val map = mapOf(Pair("lijiajun", 123), Pair("lisi", 123))
}

kotlin 面向对象

面向对象案例

以洗衣服为例子:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    var wash = WashMachine("小天鹅", 12)
    wash.open()
    println("将需要轻柔洗的衣服放进去")
    wash.close()
    wash.currentMode = 1
    wash.start()
}

class WashMachine(var modele: String, var size: Int) {
    private var isOpen: Boolean = false
    var currentMode: Int = 0

    fun open() {
        println("打开洗衣机")
        isOpen = true
    }

    fun close() {
        println("洗衣机的关门")
        isOpen = false
    }

    fun start() {
        if (!isOpen) {
            when (currentMode) {
                0 -> println("现在是初始模式,请选择一个模式")
                1 -> {
                    println("放水")
                    println("轻柔模式")
                }

                2 -> {
                    println("放水")
                    println("狂揉模式")
                }

                else -> println("模式无法识别")
            }
        } else {
            println("请关门")
        }
    }

    fun selectMode(mode: Int) {
        when (mode) {
            0 -> println("初识模式,请您选择模式")
            1 -> println("轻柔")
            2 -> println("狂揉")
            else -> println("不要乱动")
        }
    }
}

封装

像下面这种不需要在对象外面访问的函数或者变量,可以加上 private 关键字。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

private fun setMotorSpeed(speed: Int) {
        println("当前发动机的转速${speed}")
    }

继承

将父类前面加上 open 关键字,然后子类才可以继承:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    var son: Son = Son()
    son.action()
}

open class Father {
    var charactor: String = "性格内向"
    fun action() {
        println("在公共场合大声说话")
    }
}

class Son : Father() {

}

虽然子类中什么都没有,但是依然可以直接使用父类的方法文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

console文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

在公共场合大声说话

进程已结束,退出代码0

重写方法

需要父类将方法前面加上: open文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    var son: Son = Son()
    son.action()
}

open class Father {
    var charactor: String = "性格内向"
    open fun action() {
        println("在公共场合大声说话")
    }
}

class Son : Father() {
    override fun action() {
        println("儿子不在公众场合说话")
    }
}

抽象类和继承

就是有的类是有相同的部分的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

  • 人类(相同:吃饭,睡觉... 不同:上厕所...)
    • 男人
    • 女人
fun main() {
    var huaxingyu: Man = Man("huaxingyu")
    var person: Woman = Woman("awoman")
    huaxingyu.pee()
    person.pee()
}

// 抽象类
abstract class Human(var name: String) {
    abstract fun eat()
    abstract fun pee()
}

// 男人
class Man(name: String) : Human(name) {
    override fun eat() {
        println("$name,吃饭")
    }

    override fun pee() {
        println("$name,站着")
    }
}

// 女人
class Woman(name: String) : Human(name) {
    override fun eat() {
        println("$name,吃饭")
    }

    override fun pee() {
        println("$name,蹲着")
    }
}

console文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

huaxingyu,站着
awoman,蹲着

进程已结束,退出代码0

抽象类与接口

接口:接口泛指实体把自己提供给外界的一种抽象化物(可以为另一实体),用以由内部操作分离出外部沟通方法,使其能被内部修改而不影响外界其他实体与其交互的方式。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

interface文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    var man: Man = Man()
    man.eat()
}

interface IMan {
    fun eat()
}

class Man : IMan {
    override fun eat() {
        println("吃饭")
    }
}

接口与抽象类的区别:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

  • 接口是事物的能力
  • 抽象类反应的是事物的本质
class Man : IMan, Human() {
    override fun eat() {
        println("吃饭")
    }
    override fun fertility() {
        println("生育")
    }
}

class Taijian : Human() {
    override fun eat() {
        println("吃饭")
    }
}

太监和男人都是人,都可以吃饭(抽象类),但是太监不能够生育(接口),也就是太监没有继承生育的这个接口,虽然我们可以给他加,但是很明显这条个是不合理的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

委托和代理

by -> 代理文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

原来的代码,父亲和儿子都可以洗碗文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val son: BigHeadSon = BigHeadSon()
    val father: SmallHeadFather = SmallHeadFather()
    son.washing()
    father.washing()
}

// 洗完的能力
interface IWashBow {
    fun washing()
}

class BigHeadSon : IWashBow {
    override fun washing() {
        println("我是大头儿子,我在洗碗")
    }
}

class SmallHeadFather : IWashBow {
    override fun washing() {
        println("我是小头爸爸,我在洗碗")
    }
}

使用代理,父亲让儿子帮自己洗碗文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

使用这样的写法:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

class SmallHeadFather : IWashBow by BigHeadSon() {}
fun main() {
    val son: BigHeadSon = BigHeadSon()
    val father: SmallHeadFather = SmallHeadFather()
    son.washing()
    father.washing()
}

// 洗完的能力
interface IWashBow {
    fun washing()
}

class BigHeadSon : IWashBow {
    override fun washing() {
        println("我是大头儿子,我在洗碗")
    }
}

// class SmallHeadFather : IWashBow {
//     override fun washing() {
//         println("我是小头爸爸,我在洗碗")
//     }
// }

class SmallHeadFather : IWashBow by BigHeadSon() {}

console文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

我是大头儿子,我在洗碗
我是大头儿子,我在洗碗

进程已结束,退出代码0

单例模式

关于单例模式:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

单例类是一种特殊的类,它只能创建一个实例。在 Kotlin 中,您可以使用“object”关键字来定义单例类。这个实例是在第一次访问单例类的时候创建的,并且在整个应用程序中只有一个实例。

因为单例类只能创建一个实例,所以您不能使用构造函数来创建新的实例。相反,您可以使用类名来访问单例类的唯一实例。例如:

```
object MySingleton {
    fun doSomething() {
        // ...
    }
}

// 使用
MySingleton.doSomething()
```

在这个例子中,MySingleton 是一个单例类,它只有一个实例。您可以使用 MySingleton.doSomething() 来访问这个唯一的实例并调用其方法。

代码案例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    val father: SmallHeadFather = SmallHeadFather()
    father.washing()
}

// 洗完的能力
interface IWashBow {
    fun washing()
}

object BigHeadSon : IWashBow {
    override fun washing() {
        println("我是大头儿子,我在洗碗")
    }
}

// class SmallHeadFather : IWashBow {
//     override fun washing() {
//         println("我是小头爸爸,我在洗碗")
//     }
// }

class SmallHeadFather : IWashBow by BigHeadSon {}

枚举

就是做一个映射文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    println(Work.周一)
    println(Work.周一.ordinal)
}

enum class Work {
    周一, 周二, 周三, 周四, 周五, 周六, 周日
}
周一
0

进程已结束,退出代码0

密封类 Sealed class

Andriod开发24000字长文带你入门kotlin

在子类类型有限的 class ,我们可以使用密封类,或者叫做印章类。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html

fun main() {
    var son: Son.小驴 = Son.小驴()
    son.sayHello()
}

sealed class Son {
    fun sayHello() {
        println("大家好")
    }

    class 小驴() : Son()
    class 骡子() : Son()
}
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/47080.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/xcx/47080.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定