变量:
val : 声明一个不可变的变量,对应java的final变量。
val name:String = "张三"
var: 声明一个可变的变量,对应java的非final变量。
var name:String = "张三"
lateinit : 延迟初始化关键字,不用在声明变量的时候立刻赋值
(::object.isInitialized 可用来判断一个变量或对象是否已经初始化
)
lateinit var name:String // 不用立刻赋值 也不会报错
name = "张三" //后续使用中进行赋值
if(! ::name.isInitialized){
Log.e("AAA","name 还未初始化")
}
Java 与 Kotlin数据类型对照表
Java基本数据类型 | Kotlin对象数据类型 | 数据类型说明 |
---|---|---|
int | Int | 整形 |
long | Long | 长整形 |
short | Short | 短整形 |
float | Float | 单精度浮点型 |
double | Double | 双精度浮点型 |
boolean | Boolean | 布尔型 |
char | Char | 字符型 |
byte | Byte | 字节型 |
函数:
a与b是参数," :Int "是返回值类型
fun add(a: Int, b: Int): Int {
return a + b
}
条件语句:
- if 语句: 基本与java一样 ;但是: Kotlin的 if 语句可以有返回值
例如:
val value = if (a > b) {
a
} else {
b
}
- when语句:
when也有返回值
val name = "张三"
val myName = when (name) {
"张三" -> "欢迎张三" //直接返回值
"李四" -> { println("李四来了") } //直接代码块运行
is String -> print("是String类型") //判断类型
else -> "未定义" //默认返回
}
循环语句:
- while循环: 与 java 没有任何区别
- for循环:
正序遍历:0到10
for (i in 0..10) {
println(i)
}
倒序遍历:10到0:
for (i in 10 downTo 0) {
println(i)
}
有条件的遍历:
step 2:每次自加2
0 until 10 :不包含最后一个元素
for (i in 0 until 10 step 2) {
println(i)
}
类与对象:
- 创建类
class Person {
var name = ""
var age = 0
}
- 实例化类
val person = Person()
- 需要继承的类,用 open 声明
open class Person {
var name = ""
var age = 0
}
- 类的继承与实现
class Student : Person(), Eat { //继承自Person,实现了Eat接口
override fun eat() {
print("我是学生,我属于人类,我会吃")
}
}
- 类得主构造参数
class Student(name: String, age: Int) { //此括号就是主构造函数,init相当于它的函数体
init {
print("我相当于主构造函数的函数体")
}
}
- 类的次构造函数
// 一个类既有主构造函数 又有 次构造函数 次构造函数必须调用主构造函数(包括间接调用)
class Student(name: String, age: Int) {
constructor(name: String) : this(name, 12) {
print("次构造函数")
}
}
接口:
- Kotlin 接口允许默认实现
interface Eat {
fun eat() {
print("我会吃")
}
}
class Student : Person(), Eat { //继承自Person,实现了Eat接口
override fun eat() {
super.eat()
print("我是学生,我属于人类,我会吃")
}
}
可见性修饰符:
Java与Kotlin可见性修饰符对照表
修饰符 | Java | Kotlin |
---|---|---|
public | 所有类可见 | 所有类可见(默认 |
private | 当前类可见 | 当前类可见 |
protected | 当前类、子类、同一包路径下的类可见 | 当前类、子类可见 |
default | 同一包路径下的类可见 | 无 |
internal | 无 | 同一模块中的类可见 |
数据类
- 创建数据类(用 data 关键字声明)
data class DataBean(val name: String, val age: Int) {
// 没有类体 可以省略大括号
}
- 数据类的 getter、setter操作
val dataBean = DataBean("张三", 18)
// get
println(dataBean.name + dataBean.age)
// set
dataBean.name = "李四"
dataBean.age = 20
println(dataBean.name + dataBean.age)
打印结果:张三18
李四20
单例类
- 创建单例类(用 object 关键字声明)
// 在Koltin中我们不需要私有化构造函数,也不需要提供getInstance()静态方法,
//只需要把class关键字改为object,就完成了单例类的创建
object Singleton {
fun test(mlog: String) {
println(mlog)
}
}
- 调用单例类中的函数(类似java中调用静态方法)
Singleton.test("我是单例类") // 调用了Singleton中的test()函数
密封类(sealed class)
- sealed class又称为印章类或密封类,用于子类类型有限的类。
- 与when语句配合使用可以自动生成所有子类的条件分支,还不再需要额外添加else分支。
密封类创建(新建kotlin File 使用关键字sealed class来创建):
sealed class TestSealed
class Test1(val msg: String) : TestSealed() // 继承了密封类
class Test2(val erroe: String) : TestSealed() // 继承了密封类
与when配合使用的优点:
- when将不用添加else分支,还能自动生成所有子类的分支
- 每当添加新的子类时,when都会报错,让你添加新的子类分支,这样减少了程序的出错率
fun getResult(testSealed: TestSealed): String = when (testSealed) {
is Test1 -> "t1"
is Test2 -> "t2"
}
空指针检查
- 可空类型
var name:String //不可空变量
var name:String? //可空变量
- 可空类型的使用
var bean:Bean? //可空变量
bean?.getName() // ?. 操作符:当对象为空时什么都不做,不为空时正常运行
var age = bean?.getAge ?: 18 // ?: 操作符:左边表达式不为空就返回左边结果,否则返回右边结果
bean!!.getId // !!. 操作符:确定此处不会为空,不再进行空指针检查
字符串内嵌表达式
使用 $ 操作符
val name: String = "张三"
println("我是$name,请多关照!")
val bean = Bean()
println("我是${bean.getName()},请多关照!")
参数默认值 与 指定传参
fun add(a: Int = 1, b: Int = 1): Int { //参数默认值
return a + b
}
add(b = 2, a = 2) //指定传参(参数顺序可颠倒)
Kotlin中的 标准函数
- let 函数
- 主要作用:配合 ?. 操作符进行判空处理
var bean:Bean? =null
// 不用let函数(每次都需要使用?.操作符)
bean?.getName()
bean?.getAge()
//注意下面这种方式在bean为全局变量时会报错
if (bean != null) {
bean.getAge()
bean.getName()
}
// 使用let函数(正常写Lambda)
bean?.let { b ->
b.getName()
b.getAge()
}
// 使用let函数(当Lambda只有一个参数时,可以省略不写,直接用it代替)
bean?.let {
it.getName()
it.getAge()
}
- with函数
- 大多数用于 一个对象使用多次的场景
val value = with(bean) {
// 这里时bean的上下文,可直接调用bean中的方法
val name = getName()
val age = getAge()
name + age.toString() //最后一行作为返回值
}
- run函数
- run 与 with用法一样,只是写法不一样,run需要在某个对象上调用
val value = bean.run {
// 这里时bean的上下文,可直接调用bean中的方法
val name = getName()
val age = getAge()
name + age.toString()//最后一行作为返回值
}
- apply函数
- apply无法指定返回值,而是自动返回调用对象本身
实用小例子:
// 跳转界面需要传多个值,使用apply
val intent = Intent(context, SencondActivity::class.java).apply {
// Intent的上下文,可直接调用Intent中的方法
putExtra("param1", "data1")
putExtra("param2", "data2")
}
context.startActivity(intent)
定义静态方法
- 使用单例类来定义静态方法
- 注意:单例类中的所有方法都只能是静态方法
object Singleton {
fun test(mlog: String) {
println(mlog)
}
}
Singleton.test("哈哈")
- 使用companion object(伴生对象)定义静态方法
- 当我们的类中既要有静态方法,还要有普通方法时,就不能使用单例类了,伴生对象则是更好的选择
class Util {
companion object { // 写在伴生对象中的方法是静态方法
fun test() {
// 我是静态方法
}
}
fun test1() {
//我是普通方法
}
}
Util.test() //调用静态方法
val util = Util()
util.test1() //调用普通方法
- 使用@JvmStatic注解,成为真正的静态方法(不常用)
- @JvmStatic只能加在单例类或者伴生对象中的方法上(加上此注解后,在kotlin与java中都是静态方法,是真正的静态方法)
//单例类
object Singleton {
@JvmStatic
fun test() {
// 我是静态方法
}
}
//伴生对象
class Util {
companion object {
@JvmStatic
fun test() {
// 我是静态方法
}
}
}
未完待续。。。