为什么选择Kotlin:
- 官方指定:名正言顺取代 java 在 Android 开发中的地位
- 简洁、现代、安全:安全,静态语言;
- 无缝兼容 Java:互换
第一天 : Kotlin 基础
在 Kotlin 中,所有的东西都是对象,这就意味着我们可以调用任何变量的成员函数和属性。
常量、变量:
常量:预期范围内不变的量 val 常量名 = 值
变量 var
//空安全变量,有类型推断,:后可省略
var str: String = "hello" //变量名在前面,类型以冒号:隔开在后面
//可为空字符串变量
var str2: String? = null //类型后带问号?表示可为空类型(默认空安全)
优先使用val,如果不能,IDE会报错,改为var
浮点型:默认精度Double
类型安全:变量一旦定义,其类型就不能改变。即不能给变量一个不同类型的值:
var age = 12
age = "12" //错误
元组:给多个变量同时赋值,分二元(Pair)、三元(Triple)。
var (age, name, sex) = Triple(12, "twj", "male")
可空类型:(重要,特色)
表示变量可能没有值。如用户资料,手机号不能为空,但是选填部分如住址、邮箱等可以为空,形式:var 变量名:类型?,无值则为null。使用该变量时,要判空。
操作符:
+、-、*、/之间最好用空格分割
字符串 和 字符 间可以用 +
号连接
if表达式
val result = if(a>b) "大于" else 0 //表达式返回类型可以不同
when表达式
移除了switch
,用更强大的when
替代,when
子式可以是常量、变量、返回数值的表达式、返回Boolean
值的表达式,强大到用来替换if...else if
ranges 范围
懒属性(延迟加载)
val p: String by lazy {
// compute the string
}
函数
字符串模板:
作用:将变量组合成一个动态的字符串
在Java中拼接字符串的代码可读性都很差,在Kotlin字符串拼接非常简洁,只需用$后加上变量名,复杂的参数要加上{}
val user = User()
//赋值
user.name = "tutu"
user.age = "23"
//取值
val name = user.name
val age = user.age
var userInfo = "name:${user.name}, age:$age"
//输出结果:name:tutu, age:23
集合类型
数组:Array
Array<类型>` / `arrayOf(元素1, 元素2...
例: var age = arrayOf(68, 69, 70)
Map:
获取key对应的value get
/getOrDefault()--不存在时设置默认值
添加或更新:map变量名[key] = value
Lambda
一开始觉得lambda很高级完全看不懂,其实很简单的就是把接口名、方法名和参数类型省掉不写再加个 -> 罢了,明白这点了很好理解。
// 无参数无返回值
Thread(Runnable {
sleep(1000)
}).start()
// 单参数不带返回值
view.setOnClickListener { v ->
Log.e("tag", "${v.tag}")
}
// 多参数带返回值
view.setOnKeyListener(View.OnKeyListener { v, keyCode, event ->
Log.e("tag", "keyCode$keyCode, ${event.keyCode}")
if (event.keyCode == KeyEvent.KEYCODE_BACK)
return@OnKeyListener true
false
})
分组: groupby
排序: sortby
行内函数
高阶函数
类、和继承、属性、权限修饰符
第二天: 面向对象
接口的实现、接口中的属性、接口冲突规则
面向对象
对事物抽象化 建模,一个模型即为一个类
open关键字:父类是 open 子类才能继承;父类的 属性/方法 是 open 子类才能 override
定义:(open) class 类名 constructor(属性列表){ 更多的属性和方法描述 }
普通属性:与变量定义类似
open var skin = "yellow"
组合属性:由其他属性计算得来(get)
var averageLife : Double
get(){
when(this.region){ //由地区来决定平均寿命
"上海" -> {
return 69.0
}
"广东" -> {
return 68.0
}
else -> {
return 68.0
}
}
}
子类属性和属性覆盖:override var 属性名 = 属性值
属性修饰符:
private 当前类可见
protected 子类
internal 模块内
public 默认,最大,对外完全可见
数据类:
专门用于保存数据(简单数据)的类,如用户登录信息,聊天记录等
这里的保存,并不是保存的到磁盘,而是转换为文本格式,便于保存
书数据类定义:data class 类名(属性列表)
数据类的序列化:实例.toString()
列举属性:实例.componentN()
枚举类:
有限个类型的列举,其中的每一个称为枚举常量(可带初始值),每一个以逗号分隔
enum class PookerCard{
红心, 方片, 梅花, 黑桃
}
//列举枚举类的常量 :PookerCard.values()
//带构造器的枚举类
enum class Size(val height : Int){
S(150), M(160), L(170),XL(180),XXL(190)
}
//列举枚举类的某个常量 :
Size.values("XL").name // XL
Size.values("XL").oridinal //3
Size.values().joinToString{ it.name + ":" + it.height}
//S:150, M:160, L:170,XL:180,XXL:190
空判断
Kotlin的空安全设计对于声明可为空的参数,在使用时要进行空判断处理,有两种处理方式,字段后加!!像Java一样抛出空异常,另一种字段后加?可不做处理返回值为 null或配合?:做空判断处理
//类型后面加?表示可为空
var age: String? = "23"
//抛出空指针异常
val ages = age!!.toInt()
//不做处理返回 null
val ages1 = age?.toInt()
//age为空返回-1
val ages2 = age?.toInt() ?: -1
错误处理
直接展示错误: try...catch...
类型检查与转换
检查:对一个变量的类型进行辨别;转换:将变量转换为其他类型使用
类型判断 : is / !is 变量名 is Int
手动转化:强制转换:as; 安全转换:as?,安全转换失败返回null
第三天: 接口、泛型、扩展
接口:interface
实现的标准
通常用于对类进行附加功能,让类保持简洁的定义。通过实现 1 个或者 N 个接口的 组合,来实现非继承式的功能增强。
接口定义: interface 接口名{ //各种属性和方法定义 }
接口中的方法可以有默认实现,通常指该方法是固定不变的
实现接口:,接口名
//不要implement
泛型:Generics
让一个类型被“广泛”使用,即通用化。一般用于函数的参数类型定义,让函数更通用。
定义泛型函数:
fun <T> 函数名(参数名: T): 返回值 { }
//T:类型占位符
泛型约束:<类型占位符:类型>
扩展:
对既有的类增加新功能,而无需继承该类,即使无法获取其源码。
主要作用是“立即”为相关类整体上添加工具类(Utils)方法或属性,高效优雅。
扩展函数、扩展属性、扩展协议(可能将来版本支持,Swift已实现)
与接受者类(原类)中参数、名称都一样的扩展是无效的;尽量避免与已有的名字重名,如果一定要重名,参数名和类型也要不一样。
扩展属性:
普通属性扩展:
例1:整数的下一个数字
val Int.next : Int
get() = this + 1
//使用
print(3.next) //4
泛型属性扩展:
例2:数字类型半径值对应的面积—-πr2r2
val <T : Number> T.area :Double
get() = 3.14 * this.toDouble() * this.toDouble()
//使用
print(2.area) //12.56
扩展函数: fun 接受者类型.新扩展函数名(参数类型) { //函数实现 }
例1:普通函数扩展
//求整数的平方
//立即给Int类整体增加一个工具方法
fun Int.square(): Int{
return this * this
}
//使用
print(3.square())
例2:泛型函数扩展—-取数字型数组中最大数
fun <T> Array<T>.biggest() : T
where T: Number,
T: Comparable<T> {
var biggest = this[0]
for(i in 1..lastIndex){
val element = this[i]
if(element > biggest){
biggest = element
}
}
return biggest
}