第三行代码 Kotlin 学习笔记

变量和函数

变量

  • var (variable) 可变量
  • val (value) 不可变量
  • 初始化
    val a: Int = 10
    val b = 10
    

函数

  • 说明: 函数(function)与方法(method)是同一个概念,Kotlin叫函数,Java叫做方法
  • 写法:
    • 基本写法
    // 有返回值
    fun methodName(param1: Int, param2: Int): Int {
    	return 0
    }
    //没有返回值可以省略 Int
    fun methodName(param1: Int, param2: Int) {
    	//todo
    }
    
    
    • 函数中只有一句话时可以简写
    //下面两个方法等价
    fun largerNumber(num1: Int, num2: Int): Int = max(num1, num2)
    
    fun largerNumber(num1: Int, num2: Int) = max(num1, num2)
    

逻辑控制

if 条件语句

  • if 可以有返回值
    fun largerNumber(num1: Int, num2: Int) = if (num1 > num2) {
        num1
    } else {
        num2
    }
    
    fun largerNumber(num1: Int, num2: Int) = if (num1 > num2) num1 else num2
    

when 条件语句

  • 语法
    when (任意类型参数) {
    	匹配值 -> { 执行逻辑 }
    	else -> { 执行逻辑 }
    }
    
  • when 语句中如果要返回值,必须要有 else , 除非是个密封类对象
  • 用法1:
    fun getScore(name: String) = when (name) {
        "Tom" -> 86
        "Jim" -> 77
        "Jack" -> 95
        "Lily" -> 100
        else -> 0
    }
    
  • 用法2, 不带参数的 when
    fun getScore(name: String) = when {
        name.startsWith("Tom") -> 86
        name == "Jim" -> 77
        name == "Jack" -> 95
        name == "Lily" -> 100
        else -> 0
    }
    
  • 用法3,类型匹配
    fun checkNumber(num: Number) {
        when (num) {
            is Int -> println("number is Int")
            is Double -> println("number is Double")
            else -> println("number not support")
        }
    }
    
    

循环语句

  • 区间概念
    0..10 对于数学中的 [0, 10],只能是升序,
    0 until 10 即 [0, 10),只能是升序
    10 downto 0 即 [10, 0],只能是降序

  • 例子

    for (i in 0 until 10) {
        print(i) //结果:0123456789
    }
    
    // step 按指定值递增
    for (i in 0 until 10 step 2) {
        print(i) //结果:02468
    }
    
  • 遍历集合

    val list = listOf("a", "b", "c")
    for (v in list) {
        println(v)
    }
    
    val map = mapOf("key1" to 1, "key2" to 2, "key3" to 3)
    for ((k, v) in map){
        println("$k = $v")
    }
    
    

面向对象编程

创建对象不需要 new
类、方法默认都是 public final

继承与构造函数

  • 创建 public final 的类, 默认即 public final

    class Person {
    
    }
    
  • 创建 public 且可被继承的类

    open class Person {
    	//方法也要加 open, 否则默认为 public final 修饰
    	open fun eat() {
            println("person eat")
        }
    }
    
  • 继承

    class Student() : Person() {
    
    }
    
  • 主构造函数:写在类名上的构造函数;

  • 次构造函数 constructor:除主构造函数外的构造函数

  • init 结构体, 用于通过主构造函数创建对象时初始化数据

    class Student() : Person() {
    	init {
    		println("Student created")
    	}
    }
    // 当没有次构造函数且没有主构造函数时默认为有无参构造函数
    class Student : Person() {
    	init {
    		println("Student created")
    	}
    }
    
  • 注意:所有次构造函数必须直接或间接调用主构造函数

    class Student(val grade: String, name: String, age: Int) : Person(name, age) {
        init {
            println("Student created")
        }
        //通过 constructor 创建次构造函数
        constructor() : this("g") {
    
        }
        constructor(grade: String) : this(grade, "", 0) {
        }
    }
    
    open class Person(val name: String, val age: Int) {
    }
    
  • 只有次构造函数的情况,Student和Person都不用括号

    	class Student : Person {
    	    init {
    	        println("Student created")
    	    }
    
    	    //大括号可以省略
    	    constructor() : this("g")
    
    	    constructor(grade: String) : this(grade, "", 0)
    
    	    constructor(grade: String, name: String, age: Int) : super(name, age) {
    	        //do sth
    	    }
    	}
    
    	open class Person(val name: String, val age: Int) {
    	}
    

接口

  • 实现接口的写法和继承的写法类似

    
    	interface Study {
    	    fun readBooks()
    
    	    //接口可以有默认方法
    	    fun doHomework() {
    	        println("do homework")
    	    }
    	}
    
    	class Student(name: String, age: Int) : Person(name, age), Study {
    		override fun readBooks() {
    			println("student do readBooks")
    		}
    	}
    
  • Java 和 Kotlin 函数可见性修饰符对照表

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

数据类和单例类

  • 数据类, 加 data 关键字,默认会创建 get/set/equal/hashCode/copy/toString 等函数
    如果不加 data 关键字,则只会生成 get/set 方法 (val 只会生成 get 方法)
    data class Cellphone(val brand: String, val price: Double)
    
  • 单例,将 class 改为 object 即可,然后通过 类名.方法名() 调用,类似 Java 的静态方法
    kotlin中一般用单例作为工具类
    object Singleton {
    	fun singleTest() {}
    }
    
    等价于
    public final class Singleton {
    	public static final Singleton INSTANCE;
    
    	static {
    		INSTANCE = new Singleton();
    	}
    
    	public final void singleTest() {
    	}
    
    	private Singleton() {
    	}
    
    }
    

Lambda 编程

集合

  • list/set 集合

    	//不可变集合:不能增、删、改
        val list = listOf<String>("A", "B", "C")
        //可变集合
        val mutableList = mutableListOf<String>("A", "B", "C")
        mutableList[2] = "b"
        mutableList.add("D")
    
        val set = setOf<String>("A", "B", "C")
        val mutableSet = mutableSetOf<String>("A", "B", "C")
    
  • map 集合

       	val map = mapOf("A" to 65, "B" to 66, "C" to 67)
        val mutableMap = mutableMapOf("A" to 64, "B" to 66, "C" to 67)
        // 增和改的写法相同,下面依次为 增 改 删
        mutableMap["D"] = 68
        mutableMap["A"] = 65
        mutableMap.remove("B")
        // 两种遍历方式
        for (entry in mutableMap) {
            println("${entry.key} = ${entry.value}")
        }
        for ((key, value) in mutableMap) {
            println("$key = $value")
        }
    

集合的函数式 API

  • map 包装效果,将集合中的对象包装为另一个对象后返回新的集合

  • filter 过滤满足条件的对象并返回新的集合

    	// 将 Char 集合转为 Int 集合并找到集合中 >65 的值并遍历打印
    	val list = listOf<Char>('A', 'B', 'C')
    	list.map { it.toInt() }
            .filter { it > 65 }
            .forEach { println(it) } //66 67
    
  • any 有一个满足条件则返回 true

  • all 所有都满足条件则返回 true

    	val any: Boolean = list.any { it == 'A' } //true
    	val all: Boolean = list.all { it == 'A' } //false
    
  • maxBy 按给定比较参数返回最大值

    	val max: Char? = list.maxBy { it.toInt() } //'C'
    
  • Lambda 表达式简化过程演示

    	    val lambda = { c: Char -> c.toInt() }
    	    list.maxBy(lambda)
    
    	    list.maxBy({ c: Char -> c.toInt() })
    	    list.maxBy({ c -> c.toInt() })
    	    list.maxBy({ it.toInt() })
    	    list.maxBy{ it.toInt() }
    

Java 函数式 API 的使用

  • 匿名类的写法, 加 object 关键字
    Thread(object : Runnable {
        override fun run() {
            //do sth
        }
    }).start()
    
  • 可简写为
    Thread(Runnable {
    	// do sth
    }).start()
    
    // 如果接口中只有一个方法,可以将接口名省略
    Thread({
    	// do sth
    }).start()
    
    // 当 Lambda 表达式是方法的最后一个参数时,可以将表达式移到方法的外边。
    Thread() {
    	// do sth
    }.start()
    
    // 同时如果 Lambda 表达式还是方法的唯一参数,还可以将方法的括号省略
    Thread {
    	// do sth
    }.start()
    
    监听点击事件的例子
    // 完整写法
       tv.setOnClickListener(object : View.OnClickListener {
           override fun onClick(v: View?) {
           }
       })
       // 省略 object 和 方法名
       tv.setOnClickListener(View.OnClickListener {
       })
       // 省略类名
       tv.setOnClickListener({
       })
       // 移到方法括号外边
       tv.setOnClickListener() {
       }
       // 省略方法括号
       tv.setOnClickListener {
       }
    

空指针检查

  • ?. 判空

    	var l = str?.lenth
    

    等价于

    	if (str != null) {
            return str.length();
        } else {
            return null;
        }
    
  • ?: 三元运算

    	val s = str ?: ""
    

    等价于

        val s = str == null ? "" : str;
    
    	val l = str?.length ?: 0
    	// 上面句子可分解为
    	val l = str?.length
    	l = l ?: 0
    

    等价于

    	val l = str == null ? 0 : str.length;
    
  • !!. 非空断言,强制编译器不做空指针检查,如 str!!.length

  • let 标准函数,配合 ?. 操作符使用, 判空的同时处理数据

    	str?.let { 
            println(it.length)
            println(it)
        }
    

Kotlin 小魔术

字符串内嵌表达式

  • 变量前加 $ 符,如果是表达式用大括号括起来

    val a: String = "abc"
    val b: String = "cdf"
    println("a = $a, b = $b, a+b = ${a+b}")
    
  • 如果要打印"$"符,加斜杠 \$

函数参数默认值

小知识点

  • 通过类名获取class对象: Person::class.java 即 Java 的 Person.class
  • 通过对象获取class对象: person.javaClass 即 Java 的 person.getClass()
  • Any 是 Kotlin 中所有类的基类,相当于 Java 中的 Object

标准函数和静态方法

标准函数即是在 Standard.kt 里定义的函数

标准函数 let、with、run、apply

  • let obj.let{ it -> }, 最后一行作为返回值
  • with with(obj) { 这里面调用的都是‘obj’对象的方法 }, 最后一行作为返回值
  • run obj.run { 这里面调用的都是‘obj’对象的方法 }, 最后一行作为返回值
  • apply obj.apply { 这里面调用的都是‘obj’对象的方法 }, 返回值为‘对象’本身
  • repeat repeat(n) {}, 重复 Lambda 表达式 n 次

静态方法

关键字

  • inner class, 定义内部类
  • companion object { }, 定义静态成员/函数
  • const val, 常量,只能在companion object、单例类或顶层作用域中使用
  • vararg, 英文意思variable argument, 对应 Java 的可变参数列表:(int... array)

延迟初始化和密封类

延迟初始化 lateinit var

  • lateinit 后面只能是 var, 不能用于 val
  • 判断是否已经初始化 ::adapter.isInitialized
  • 例子
    private lateinit var adapter: MsgAdapter
    
    fun method(){
    	if(!::adapter.isInitialized){
    		adapter = MsgAdapter()
    	}
    }
    

密封类 sealed class

  • 用法: sealed class 类名
  • 作用: when 语句传入密封类对象作为条件时,编译器会自动检查该类所有的子类,并强制要求你将每一个子类所对应的条件全部处理
  • 优点: 不需要 else 了; 编译器会自动检测所有条件防止遗漏,更安全了。
  • 注意: 密封类及其所有子类只能定义在同一个文件顶层位置,不能嵌套在其他类中。
  • 但是,我没测不出效果

扩展函数和运算符重载

扩展函数

  • 建议:

    哪个类添加扩展函数,就定义一个同名的 Kotlin 文件
    最好将扩展函数定义成顶层方法,这样可以让扩展函数有全局的访问域

  • 语法:
	fun String.lettersCount(): Int {
	    var count = 0
	    for (char in this) {
	        if (char.isLetter()) {
	            count++
	        }
	    }
	    return count
	}
  • 以下是 Kotlin 自带的扩展函数的例子
    IO流对象.use {},用于自动关闭流
    BufferedReader.forEachLine {}, 用于读取每一行并回调到 Lambda 表达式中

运算符重载

  • 语法, 函数前加关键字:operator

    	//重载加法
    	operator fun plus(money: Money) {
    
    	}
    
  • 语法糖表达式与实际调用函数对照

    法糖表达式实际调用函数中英文解释
    + ba.plus(b)
    - ba.minus(b)
    * ba.times(b)
    / ba.div(b)除 divide
    % ba.rem(b)求余 remainder
    ++a.inc()自增 increase
    a.dec()自减 decrease
    aa.unaryPlus()一元加
    aa.unaryMinus()一元减
    aa.not()
    == ba.equals(b)恒等于
    > b, a < b, a >= b, a <= ba.compareTo(b)大于
    …ba.rangeTo(b)区间
    [b]a.get(b)获取
    [b] = ca.set(b, c)设置
    in bb.contains(a)包含

高阶函数

高阶函数定义

  • 语法: (String, Int) -> Unit
    括号内是函数的参数,Unit是返回值,Unit表示没有返回值,相当于 Java 的 void
  • 函数引用: ::plus, 将普通函数 plus 变为方法参数
    val result = num1AndNum2(num1, num2, ::plus)
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值