基本类型的数组 是没有自动装箱拆箱的过程,而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好.
在kotlin ,要用专门的数组类才能免于自动装拆箱 (IntArray FloatArray LongArray)复制代码
集合分为两种类型:只读的和可变的。这里的只读有两层意思:
java
如下是三种集合类型建立不可变和可变实例的例子:数组
listOf()
建立不可变的 List
,mutableListOf()
建立可变的 List
。setOf()
建立不可变的 Set
,mutableSetOf()
建立可变的 Set
。mapOf()
建立不可变的 Map
,mutableMapOf()
建立可变的 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 只表示只读复制代码
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 函数以外的其余地方没法访问这个嵌套函数。复制代码
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
。Kotlin的lambda表达式始终用花括号包围,花括号中经过 箭头(->)将实参和函数体分开,
post
lambda语法结构:
性能
{x:Int, y:Int -> x+y }
ui