快速入门Kotlin语言(基本语法概要)

  • 引言
  • 基本数据类型
  • 常量和变量
  • 函数
  • 字符串模板
  • 逻辑控制
  • 非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 岁")
    }
  • 结果:
101112131415
  • 还可以到序,用 downTo ,每次递减 1:
 //输出年龄
    for (i in 15 downTo 10) {
        println("$i 岁")
    }
  • 可以设置,每次递减或者递加的步数,用 step:
    //输出年龄
    for (i in 15 downTo 10 step 2) {
        println("$i 岁")
    }
  • 结果:
151311

十,集合

  • 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=后裔}

十一,结语

参考资料:

谢谢阅读,如有错误和侵权,望联系作者指正!本文完毕~

  • 3
    点赞
  • 9
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

王玉见

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值