- 引言
- 基本数据类型
- 常量和变量
- 函数
- 字符串模板
- 逻辑控制
- 非null检测
- 类
- 区间
- 集合
- 结语
一,引言
- Kotlin [1] (科特林)是一个用于现代多平台应用的静态编程语言 [2] ,由 JetBrains 开发。
- 使用 Kotlin 更快地编写更出色的 Android 应用。 Kotlin 是一种新型的静态类型编程语言,有超过 60% 的专业 Android 开发者在使用,它有助于提高工作效率、开发者满意度和代码安全性。
–来自Google 开发者平台数据 - GitHub 托管地址
二,基本类型
Kotlin完全抛弃了Java中的基本数据类型,全部使用了对象数据类型。举个栗子:在Java中,int 是一个关键字,有自己的包装类Integer,而在Kotlin中,Int就是一个类,有自己的方法和继承结构。
三,常量和变量
- 常量用 val 关键字标识,只能为其赋值一次,类似于 Java 中的 final 变量。
//定义整形常量
val x: Int
//定义整形变量 赋初始值
val y: Int = 2021
//赋初始值 才能使用
x = 2021
println(x) //2021
println(y) //2021
//再次重新赋值报错
x=2022 //Val cannot be reassigned
- 变量用 var 关键字标识,可以重新赋值,类似于 Java 中的非 final 变量。
//定义整形变量 赋初始值
var x: Int = 2021
//打印值
println(x) //2021
//再次赋值
x = 2022
//打印值
println(x) //2022
- 根据赋值,自动推断数据类型
//明确数据类型 Int
var a: Int = 2021
//自动推断为 Int 型
var b = 2021
//自动推断为 String 型
var c = "Hello,Kotlin"
四,函数
- 定义规则
fun methodName(param1: Int, param2: Int = 2021): Int {
return 0
}
- fun 是声明函数的关键字,无论定义什么函数,都要用 fun 来声明;
- methodName 是函数名,定义时最好见文知义;
- () 中可以定义多个输入的参数,并可以赋初始值;
- () 后面是返回值类型,可省略;
- {} 之间是函数体,可以编写具体的逻辑。
/**
- 比较两个整数的大小
- @param a
- @param b
- @return 最大值
*/
fun getMaxValue(a: Int, b: Int): Int {
if (a > b) {
return a
} else {
return b
}
}
- 还可以,将函数体作为返回值,直接返回,return 可以省略,Kotlin 可以自动推断出返回值类型。
/**
- 比较两个整数的大小
- @param a
- @param b
- @return 最大值
*/
fun getMaxValue1(a: Int, b: Int) = if (a > b) a else b
五,字符串模板
- 定义规则
模板表达式以美元符 $ 开头,由一个简单的字符串构成:
$ 字符串
如果表达式非常复杂,可以用大括号 {} 包括起来:
$ {字符串}
//定义常量 a
val a: Int = 2021
//定义常量 b
val b: Int = 2021
//打印常量 a
println("a 的值:$a")
//打印 a + b 的值
println("a + b 的值:${a + b}")
a 的值:2021
a + b 的值:4042
六,逻辑控制
- 在 Kotlin 中,和 Java 一样,也有逻辑控制语句,像常用的 if,when,for 循环等等,通过这些控制语句,才能编写相应的逻辑代码。
- if 控制语句
在 Kotlin 中,if 控制语句,有返回值。
/**
* 比较两个数的大小
* @param a
* @param b
* @return 返回最大值
*/
fun getMaxNumber(a: Int, b: Int): Int {
val maxNumber = if (a > b) {
a
} else {
b
}
return maxNumber
}
- 你会发现,maxNumber 是一个多余的常量,我们可以精简下代码:
/**
* 比较两个数的大小
* @param a
* @param b
* @return 返回最大值
*/
fun getMaxNumber(a: Int, b: Int): Int {
return if (a > b) {
a
} else {
b
}
}
- 当函数只有一行逻辑体的时候,我们可以省略函数体部分,return 后面的逻辑可以理解为一行代码,只是 return 后面的返回值而已,我们可以再次精简下代码:
/**
* 比较两个数的大小
* @param a
* @param b
* @return 返回最大值
*/
fun getMaxNumber(a: Int, b: Int) = if (a > b) {
a
} else {
b
}
- 还可以,再次精简下代码:
/**
* 比较两个数的大小
* @param a
* @param b
* @return 返回最大值
*/
fun getMaxNumber(a: Int, b: Int) = if (a > b) a else b
-
when 控制语句
-
将它的参数与所有的分支条件顺序比较,直到某个分支满足条件:
/**
* 查询学生的信息
* @param name 学生名称
* @return 学生信息
*/
fun getClassName(name: String) = when (name) {
"张三" -> "7年级1班"
"李四" -> "7年级3班"
else -> "查询不到该学生的信息!"
}
- Kotlin 还可以判断类型,用 is :
/**
* 获取数字的类型
* @param number
*/
fun getNmuberType(number: Number) {
when (number) {
is Int -> println("number is Int")
is Double -> println("number is Double")
else -> println("none of the above")
}
}
-
for - in 循环语句
-
for 循环,可以对任何提供迭代器(iterator)的对象进行遍历。
-
我们定义一个数组:
var heroNames = arrayOf("亚瑟", "刘邦", "露娜", "玄策")
- 循环遍历该数组,我们可以通过下面的方式:
- 通过角标:
for (i in heroNames.indices) {
println("这个英雄 在 $i 是 ${heroNames[i]}")
}
- 通过获取数据对象:
for (item in heroNames) {
println(item)
}
- 通过库函数:
for ((index, value) in heroNames.withIndex()) {
println("$index ----$value")
}
- 通过 iterator 迭代器:
var iterator = heroNames.iterator()
while (iterator.hasNext()) {
println(iterator.next())
}
- while 条件语句
- while(条件)…逻辑体
- do{}…while()
/**
* 打印10以内的正偶数
*/
fun getNumByWhile() {
var i: Int = 10
var j: Int = 10
while (i >= 0) {
if (i % 2 == 0) {
println("偶数i:$i")
}
i--
}
do {
if (j % 2 == 0) {
println("偶数j:$j")
}
j--
} while (j >= 0)
}
-
return
-
默认从最直接包围它的函数或者函数返回。
-
break
-
终止最直接包围它的循环。
-
continue
-
结束当前,继续下一次直接包围它的循环。
七,非空检测
- Kotlin 语言有很大的一个特点,就是做非空检测,减少开发者因 null 导致的一系列的异常错误。
//定义变量 a
var a: Int
//定义常量 b 赋空值报错
val b: String = null//Null can not be a value of a non-null type String
//赋空值报错
a = null//Null can not be a value of a non-null type In
- 在 Kotlin 语言中,默认定义的变量和常量,都是非空的,任何用到它的地方都是非空,我们可以放心的使用。
- 如何定义一个可空的数据呢?Kotlin 语言中这样定义:在对应的数据类型后面加 ?, ? 操作符表示当对象不为空时正常调用相应的方法,当对象为空时则什么都不做。
//定义变量 a
var a: Int?
//定义常量 b 赋空值正常
val b: String? = null
赋空值正常
a = null
- 既然,数对象可能为空,那么在使用的时候,如何检测非空呢?
- 直接判读 非空 !=null
//获取 b 的长度
var lenght = if (b != null) b.length else -1
- 安全调用,在对应的可空数据类型后面,也加上可空符 ?
//获取 b 的长度
b?.length//表示:b 不为空才可以调用 length 属性
var lenght = b?.length ?: -1
- 通过安全调用操作符,我们可以获取某个对象中的某个属性的某个值,例如:获取KPL中EDG(如果参赛)中露娜(如果在玩)使用的皮肤,可以如下调用:
//如果任意一个属性(环节)为空,这个链式调用就会返回 null
KPL.EDG?.LUNA?.SKIN
八,类
- 万物皆对象,Java是一门面向对象编程语言,Kotlin 语言也是类似的。定义一个类后,该类具有相应的特征,可以继承一个父类,重写方法,也可以实现接口等等。
- Any:
所有类的基类,默认继承(类似于 Java 中 Object 类):
public open class Any {
public open operator fun equals(other: Any?): Boolean
public open fun hashCode(): Int
public open fun toString(): String
}
- Kotlin 中使用关键字 class 声明类:
//定义 Animal 动物类
class Animal {
var name: String = ""
var age: Int = 0
fun getInfo() {
println("name: $name,age: $age")
}
}
- 可以生成类的实例,修改属性值并调用相关的方法:
//类的实例
var animal: Animal = Animal()
//修改熟悉值
animal.name = "狗"
//调用方法
animal.getInfo()
- 打印结果:
name: 狗,age: 0
- 带参数的类
//定义带参数的电脑类
class Computer(var brand: String, var price: Double) {
fun getInfo() {
println("brand: $brand,price: $price")
}
}
- 修改属性调用相关的方法
Computer("lenovo", 6655.00).getInfo()
- 打印结果:
brand: lenovo,price: 6655.0
- 一个类的初始化代码,可以放到以 init 关键字作为前缀的初始化块(initializer blocks)中。
//定义带参数的电脑类
class Computer(var brand: String, var price: Double) {
init {
//初始化代码
getInfo()
}
fun getInfo() {
println("brand: $brand,price: $price")
}
}
- 继承
Kotlin 中,一个类默认是不可以被继承的,可以添加 open 关键字让该类可以被继承。
open class Animal {
}
- 子类继承父类,可以用 :
class Cat : Animal() {
}
- Cat 类不仅拥有父类 Animal 的属性和函数,还可以定义自己的属性和函数。父类的函数加上 open 关键字才可以被重写,子类重写父类的函数也要加上 override 关键字。
open fun getInfo() {
println("name: $name,age: $age")
}
override fun getInfo() {
super.getInfo()
}
- 如果你想禁止再次覆盖,使用 final 关键字。
final override fun getInfo() {
super.getInfo()
}
- 初始化顺序
本类中初始化函数和属性值,按照逻辑顺序执行,子类继承父类,先执行父类的后执行子类的逻辑:
//定义 Animal 动物类
open class Animal {
var name: String = "我是父类的属性".also(::println)
init {
println("我是父类的 init 函数")
}
}
//定义猫类继承动物类
class Cat : Animal() {
var nameCat: String = "我是子类的属性".also(::println)
init {
println("我是子类的 init 函数")
}
}
- 打印结果:
我是父类的属性
我是父类的 init 函数
我是子类的属性
我是子类的 init 函数
- 单例类
Kotlin中使用object关键字可以定义一个单例类:
object School {
fun getSchoolName() {
println("欢迎来到清华大学")
}
}
- 调用
可以通过类名,直接调用对应的属性值和函数,类似于 Java 中的静态方法的调用。但是在 Kotlin 中,它帮我们生产了一个 School 实例,并且保证全局只有一个 School 实例。
School.getSchoolName()
- 接口
Kotlin 中,接口和 Java 的关键字是相同的,使用 interface。 - 定义一个接口
interface CommonMethod {
fun eat()
fun play()
}
- 实现一个接口,用 :后给接口名;也可以实现多个接口。
class Dog : CommonMethod {
override fun eat() {
}
override fun play() {
}
}
九,区间
- 在 Kotlin 语言中,我们可以用 a … b 表示一个 a 到 b 区间,数学中表示:[a,b] 两边都闭合的。判断是否在改区间,用 in ,不在该区间用 !in 。
- 定义区间 [a,b] :
//年龄在10岁(包含10)到15岁(包含15岁)的年龄段
10..15
- 也可以定义一个左开右闭的区间 [a,b) :
//年龄在10岁(包含10)到15岁(不包含15岁)的年龄段
10 until 15
- 打印年龄,每次递加1:
//输出年龄
for (i in 10..15) {
println("$i 岁")
}
- 结果:
10 岁
11 岁
12 岁
13 岁
14 岁
15 岁
- 还可以到序,用 downTo ,每次递减 1:
//输出年龄
for (i in 15 downTo 10) {
println("$i 岁")
}
- 可以设置,每次递减或者递加的步数,用 step:
//输出年龄
for (i in 15 downTo 10 step 2) {
println("$i 岁")
}
- 结果:
15 岁
13 岁
11 岁
十,集合
- Kotlin 标准库提供了一整套用于管理集合的工具,类似于 Java 中的 Set,List,Map都有自己的实现类,这些集合接口与相关函数位于 kotlin.collections 包中Kotlin 中。
根据操作,分为不可变和可变集合: - 不可变:一个 只读 接口,提供访问集合元素的操作。
- 可变: 一个 可读写 接口,通过写操作扩展相应的只读接口:添加、删除和更新其元素。
- Collection - 它是集合结构层次的根,此接口表示一个只读集合的共同行为:检索大小、检测是否为成员等等。 Collection 继承自 Iterable 接口,它定义了迭代元素的操作。
- Collection 源码:
public interface Collection<out E> : Iterable<E> {
public val size: Int
public fun isEmpty(): Boolean
public operator fun contains(element: @UnsafeVariance E): Boolean
override fun iterator(): Iterator<E>
public fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean
}
- MutableCollection
- 是一个可读写集合
- MutableCollection 源码:
public interface MutableCollection<E> : Collection<E>, MutableIterable<E> {
override fun iterator(): MutableIterator<E>
public fun add(element: E): Boolean
public fun remove(element: E): Boolean
public fun addAll(elements: Collection<E>): Boolean
public fun removeAll(elements: Collection<E>): Boolean
public fun retainAll(elements: Collection<E>): Boolean
public fun clear(): Unit
}
- 子类 List
- List 是一个有序、可以有重复元素的只读集合,可以通过索引 访问数据。
- List 源码:
public interface List<out E> : Collection<E> {
override val size: Int
override fun isEmpty(): Boolean
override fun contains(element: @UnsafeVariance E): Boolean
override fun iterator(): Iterator<E>
override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean
public operator fun get(index: Int): E
public fun indexOf(element: @UnsafeVariance E): Int
public fun lastIndexOf(element: @UnsafeVariance E): Int
public fun listIterator(): ListIterator<E>
public fun listIterator(index: Int): ListIterator<E>
public fun subList(fromIndex: Int, toIndex: Int): List<E>
}
- 创建 List 进行相关的操作
//创建 List
val heros = listOf("大乔", "后裔", "伽罗")
println("heros 的大小:${heros.size}")
println("heros 的第二个英雄是:${heros[1]}")
println("heros 的第三个英雄是:${heros.get(2)}")
println("大乔在 heros 的位置是:${heros.indexOf("大乔")}")
//打印数据
var iterator = heros.iterator()
while (iterator.hasNext()) {
println(iterator.next())
}
- 打印结果:
heros 的大小:3
heros 的第二个英雄是:后裔
heros 的第三个英雄是:伽罗
大乔在 heros 的位置是:0
大乔
后裔
伽罗
- 子类 MutableList
- 可读写的 List , 有相关的删除、添加等操作功能。
- MutableList 源码:
public interface MutableList<E> : List<E>, MutableCollection<E> {
override fun add(element: E): Boolean
override fun remove(element: E): Boolean
override fun addAll(elements: Collection<E>): Boolean
public fun addAll(index: Int, elements: Collection<E>): Boolean
override fun removeAll(elements: Collection<E>): Boolean
override fun retainAll(elements: Collection<E>): Boolean
override fun clear(): Unit
public operator fun set(index: Int, element: E): E
public fun add(index: Int, element: E): Unit
public fun removeAt(index: Int): E
override fun listIterator(): MutableListIterator<E>
override fun listIterator(index: Int): MutableListIterator<E>
override fun subList(fromIndex: Int, toIndex: Int): MutableList<E>
}
//创建 MutableList
val heroRankings = mutableListOf("娜可露露", "公孙离", "镜")
//添加元素
heroRankings.add("张良")
//移除元素
heroRankings.remove("镜")
println("heroRankings 的数值:$heroRankings")
- 打印结果:
heroRankings 的数值:[娜可露露, 公孙离, 张良]
- 子类 Set
- Set 是一组无序、元素不可以重复的只读集合。
- Set 源码:
public interface Set<out E> : Collection<E> {
override val size: Int
override fun isEmpty(): Boolean
override fun contains(element: @UnsafeVariance E): Boolean
override fun iterator(): Iterator<E>
override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean
}
//创建 Set
var names = setOf("鲁班七号", "后裔", "张良")
println("names 的大小:${names.size}")
println("names :$names")
- 打印结果:
names 的大小:3
names :[鲁班七号, 后裔, 张良]
- 子类 MutableSet
- MutableSet 是一组无序、元素不可以重复的可读写集合。
- Mutable 源码:
public interface MutableSet<E> : Set<E>, MutableCollection<E> {
override fun iterator(): MutableIterator<E>
override fun add(element: E): Boolean
override fun remove(element: E): Boolean
override fun addAll(elements: Collection<E>): Boolean
override fun removeAll(elements: Collection<E>): Boolean
override fun retainAll(elements: Collection<E>): Boolean
override fun clear(): Unit
}
//创建 MutableSet
var animals = mutableSetOf("狗", "猫", "老虎")
animals.add("猫")
animals.remove("老虎")
println("animals 的大小:${animals.size}")
println("animals 的值:$animals")
- 打印结果:
animals 的大小:2
animals 的值:[狗, 猫]
- Map<K, out V>
- 不是 Collection 接口的继承者;但是它也是 Kotlin 的一种可读集合类型。是一组键值对,键是唯一的,值可以重复。
- Map 源码:
public interface Map<K, out V> {
public val size: Int
public fun isEmpty(): Boolean
public fun containsKey(key: K): Boolean
public fun containsValue(value: @UnsafeVariance V): Boolean
public operator fun get(key: K): V?
public val keys: Set<K>
public val values: Collection<V>
public val entries: Set<Map.Entry<K, V>>
public interface Entry<out K, out V> {
public val key: K
public val value: V
}
}
//创建 Map<K,V>
var address = mapOf("小名" to 2021, "小王" to 2022)
println("mapHeros 的所有的 keys: ${address.keys}")
println("mapHeros 的所有的 values: ${address.values}")
println("小名在哪个位置:${address["小名"]}")
println("编号为2021的英雄是否存在:${2021 in address.values}")
- 打印结果:
mapHeros 的所有的 keys: [小名, 小王]
mapHeros 的所有的 values: [2021, 2022]
小名在哪个位置:2021
编号为2021的英雄是否存在:true
- MutableMap<K, V>
- Map 的子类、可读写的集合。
- MutableMap 源码:
public interface MutableMap<K, V> : Map<K, V> {
public fun put(key: K, value: V): V?
public fun remove(key: K): V?
@SinceKotlin("1.1")
@PlatformDependent
public fun remove(key: K, value: V): Boolean {
// See default implementation in JDK sources
return true
}
public fun putAll(from: Map<out K, V>): Unit
public fun clear(): Unit
override val keys: MutableSet<K>
override val values: MutableCollection<V>
override val entries: MutableSet<MutableMap.MutableEntry<K, V>>
public interface MutableEntry<K, V> : Map.Entry<K, V> {
public fun setValue(newValue: V): V
}
}
//创建 MutableMap<K,V>
var ranking = mutableMapOf(1 to "鲁班", 2 to "安琪拉")
ranking.put(3, "后裔")
println("ranking 的值:$ranking")
- 打印结果:
ranking 的值:{1=鲁班, 2=安琪拉, 3=后裔}
十一,结语
参考资料:
- Kotlin 中文网 https://www.kotlincn.net/
- 【第一行代码】https://www.ituring.com.cn/book/2744
谢谢阅读,如有错误和侵权,望联系作者指正!本文完毕~