kotlin 零散笔记

装箱

基本类型的数组 是没有自动装箱拆箱的过程,而list是有的 

对于基本类型使用,推荐用数组,性能会好点

kotlin装箱须要根据场合

对于 Int 这样的基本类型,尽可能用不可空变量
var a: Int = 1 // unbox
var b: Int? = 2 // box    会转成  Integer.parse(2) 执行装箱
var list: List<Int> = listOf(1, 2) // box
知足如下条件就不会执行装箱
1 不可空类型
2 使用 IntArray FloatArray复制代码

数组写法

kotlin 数组不支持协变 就是子类数组对象不能赋值给父类的数组变量

在kotlin 数组的写法变成 泛型式写法   arrayOf("","","")

var array: IntArray = intArrayOf(1, 2) //这种是 unbox 的

kotlin 里用专门的基本类型数组类 (IntArray FloatArray LongArray) 才能够免于装箱拆箱。

元素不是基本类型时,相比 Array,用 List 更方便些
复制代码

集合

支持协变 指的是:子类类型的list 能够赋值给父类的list

List 以固定顺序存储一组元素,元素能够重复。    ===>listOf("a", "b", "c") 支持协变

Set 存储一组互不相等的元素,一般没有固定 顺序.  ===>setOf("a", "b", "c")  支持协变

Map 存储 键-值对的数据集合,键互不相等,但不一样的键能够对应相同的值。

var map = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 3)
map.put("key1", 2)
map["key1"] = 2  
val value1 = map.get("key1")               
val value2 = map["key2"]
操做函数: forEach filter map flamap
惰性集合sequenceOf    只有使用的使用时候才会执行复制代码


用数组仍是list

list相对于数组 功能更丰富,可是数组基本类型的数组是没有自动装拆箱过程,而list是有的,

对于基本类型  ,数组的性能会比list好. 

在kotlin ,要用专门的数组类才能免于自动装拆箱 (IntArray FloatArray LongArray)复制代码

可变集合/不可变集合

集合分为两种类型:只读的和可变的。这里的只读有两层意思:
java

  • 集合的 size 不可变
  • 集合中的元素值不可变

如下是三种集合类型建立不可变和可变实例的例子:数组

  • listOf() 建立不可变的 ListmutableListOf() 建立可变的 List
  • setOf() 建立不可变的 SetmutableSetOf() 建立可变的 Set
  • mapOf() 建立不可变的 MapmutableMapOf() 建立可变的 Map
不可变的 能够经过 toMutable*() 系函数转换成可变的集合,返回的是一个新建的集合,原有的集合仍是不可变的,因此只能对函数返回的集合修改。


类构造和对象

主构造器的参数声明时加上 var 或者 val,就等价于在类中建立了该名称的属性
1 类默认是public final,   标识符 : 不只能够表示继承,还能够表示 Java 中的 implement  基类Any

2 构造函数单独用了一个 constructor 关键字来和其余的 fun 作区分。

3 Kotlin 里的类默认是 final 的,是不可继承的  须要open 声明

4 override 是有遗传性的(若是要关闭 子类的方法写成final override机可),open 没有遗传性

5 open 与 abstract关键字区别,abstract修饰的类没法直接实例化,须要被继承

6 类型判断及强转 is 、as、as?(可空类型使用)

7 init 代码块是紧跟在主构造器以后,先于次构造器执行的   
 
8 把主构造器当作身体的头部,那么 init 代码块就是颈部,次构造器就至关于身体其他部分。

9 关键字var val const open constructor overrider abstract Any objcet 修饰的类是单例类 ,(对象申明 对象表达)单例饿汉式的单例,而且实现了线程安全。

10 修饰符

11 kotlin实现匿名类写法

val listener = object: ViewPager.SimpleOnPageChangeListener() {
    override fun onPageSelected(position: Int) {
        // override
    }
}   

public:公开,可见性最大,哪里均可以引用。
private:私有,可见性最小,根据声明位置不一样可分为类中可见和文件中可见。
protected:保护,至关于 private + 子类可见。
internal:内部,仅对 module 内可见。
@hide 限制客户端访问复制代码

若是类中有主构造器,那么其余的次构造器都须要经过 this 关键字调用主构造器,能够直接调用或者经过别的次构造器间接调用。若是不调用 IDE 就会报错:
安全

class User constructor(var name: String) {
    constructor(name: String, id: Int) {
    // 👆这样写会报错,Primary constructor call expected
    }
}

从主构造器的特性出发,一旦在类中声明了主构造器,就包含两点必须性:建立类的对象时,无论使用哪一个次构造器,
都须要主构造器的参与第一性:

在类的初始化过程当中,首先执行的就是主构造器若是把主构造器当作身体的头部,那么 init 代码块就是颈部,
次构造器就至关于身体其他部分。

若是在主构造器的参数声明时加上 var 或者 val,就等价于在类中建立了该名称的属性(property)
而且初始值就是主构造器中该参数的值。复制代码


常量

class Sample {
    companion object {
         👇                  // 👇
        const val CONST_NUMBER = 1
    }
}

const val CONST_SECOND_NUMBER = 2 编译期常量 

Kotlin 的常量必须声明在对象(包括伴生对象)或者「top-level 顶层」中,由于常量是静态的。

Kotlin 新增了修饰常量的 const 关键字。

Kotlin 中只有基本类型和 String 类型能够声明成常量。

val 只表示只读复制代码

object、companion object 、top-level

juejin.im/post/5d70a2… 这里单独做了笔记
bash

若是写工具类 那就直接建立一个文件 在top-level层声明ide

若是只是针对类,而不是针对外部使用者  就能够写成 companion object 或者object函数

函数

  • 本地函数(嵌套函数)

fun login(user: String, password: String, illegalStr: String) {
           👇 
    fun validate(value: String, illegalStr: String) {
      if (value.isEmpty()) {
          throw IllegalArgumentException(illegalStr)
      }
    }
   👇
    validate(user, illegalStr)
    validate(password, illegalStr)
}
这里将共同的验证逻辑放进了嵌套函数 validate 中,
而且 login 函数以外的其余地方没法访问这个嵌套函数。复制代码
  • 返回Unit的函数
  • 返回Nothing函数
  • 单表达式函数
  • 中缀表示法
  • 成员函数
  • 局部函数(本地函数)
  • 泛型函数
  • 内联函数
  • 扩展函数
  • 高阶函数
  • 尾递归函数

kotlin内置关键字

any

data 数据类 自动生成getset

inner 内部类申明 区别于嵌套类是能够访问外部类成员

object

sealed

open 

constructor

require  

inline  

suspend 挂起提醒函数  在协程与withContext配套使用  
 
tailrec 搭配尾递归函数,函数的最后一行是函数调用的场景,是递归的一种特殊情形。尾调用不必定是递归调用

(待增长……)

复制代码


命名参数

fun sayHi(name: String = "world", age: Int) {
    ...
}
      👇   
sayHi(age = 21) 

在调用函数时,显式地指定了参数 age 的名称,这就是「命名参数」。

Kotlin 中的每个函数参数均可以做为命名参数。
复制代码


位置参数

1 与命名参数相对的一个概念被称为「位置参数」,也就是按位置顺序进行参数填写。fun sayHi(name: String = "world", age: Int, isStudent: Boolean = true, isFat: Boolean = true, isTall: Boolean = true) {
    ...
}
调用 :sayHi(name = "wo", age = 21, isStudent = false, isFat = true, isTall = false)

2 若是函数混用位置参数与命名参数,那么全部的位置参数都应该放在第一个命名参数以前fun sayHi(name: String = "world", age: Int) {
    ...
}
sayHi(name = "wo", 21) // IDE 会报错,Mixing named and positioned arguments is not allowed
sayHi("wo", age = 21) // 这是正确的写法复制代码


?. 和 ?:

val str: String? = "Hello"
                             👇
val length: Int = str?.length ?: -1
意思是若是左侧表达式 str?.length 结果为空,则返回右侧的值 -1
复制代码

Elvis 操做符还有另一种常见用法
工具

fun validate(user: User) {
    val id = user.id ?: return // 👈 验证 user.id 是否为空,为空时 return 
}

// 等同于

fun validate(user: User) {
    if (user.id == null) {
        return
    }
    val id = user.id
}复制代码


泛型通配符

定义:带上界和下界的通配符?      与类型上界不是一个东西  T extends Object

区别:?通配符上下界 一个是能不能读我或能不能写我,   类型上界只是限制类型范围

不支持协变:子类的list泛型是不能赋值给父类list的泛型,引起一个类型擦除概念因为有类型擦除存在,保证类型
的安全,java给泛型设置了这种限制

kotlin也有以上的限制 ,由此  引起出泛型通配符,解决了限制  达到协变

java:
List<? extends TextView>   返回的类型对象 能使用get相似的     但不能set值
List<? super Button>       返回的类型对象 不能使用get一类的   但能set值 

kotlin里面变成 :
List<out TextView> out表示 这个参数 只用来输出,不用来输入,只能读我 不能写我
List<in Button>    in 表示 这个参数 只用来输入,不用来输出,只能写我,不能读我

还能够用在泛型的类型参数上  interface Proucer<out T> {}
泛型的继承 在kotlin 是  <T> where T :    (一个以上继承就须要where关键字)复制代码
  • 使用关键字 out 来支持协变,等同于 Java 中的上界通配符 ? extends
  • 使用关键字 in 来支持逆变,等同于 Java 中的下界通配符 ? super

Lambda

Kotlin的lambda表达式始终用花括号包围,花括号中经过 箭头(->)将实参和函数体分开,
post

lambda语法结构:
性能

{x:Int, y:Int -> x+y }ui

相关文章
相关标签/搜索