Kotlin基础语法
Kotlin基础语法
Kotlin内置数据类型
| 名称 | 释义 | 
|---|---|
| String | 字符串 | 
| char | 字符 | 
| Boolean | 布尔型 | 
| Int | 整型 | 
| Float | 单精度浮点型 | 
| Double | 双精度浮点型 | 
| List | 集合 | 
| Set | 无重复元素集合 | 
| Map | 键值对集合 | 
变量
可读可写变量
var name: String = "Kotlin"
name = "C++"
println(name)
可读变量
val name: String = "Kotlin"
//下列变量不可修改,因为声明成val,只能进行读操作,不能进行写操作
//name = "C++" 
println(name)
自动类型推导机制
根据定义变量时进行初始化,系统可以根据初始化值自动进行类型推导,进而可以省略类型声明
val name = "Kotlin" //String
val age = 5 //Int
val sex = m' //char
val score = 99.99 //Doble
when表达式
val week = 5
    val info = when(week){
        1-> "星期一"
        2-> "星期二"
        3-> "星期三"
        4-> "星期四"
        5-> "星期五"
        6-> "星期六"
        7-> "星期天"
        else-> "错误类型"
    }
    println(info)
range表达式
  val score = 70
    when (score) {
        in 0..59 -> {
            println("不及格")
        }
        in 60 ..79 -> {
            println("及格")
        }
        in 80 .. 89 -> {
            println("良好")
        }
        else -> {
            println("优秀")
        }
    }
字符串模版
 val name = "Kotlin"
    val age = 7
    val score = 32
    val detail = "I am $name and $age,I got ${score+10} in the last test."
    println(detail)
函数
函数定义
- 在Kotlin中函数默认访问类型为Public,此处我声明为private
- fun为声明函数关键字
- add为函数名
- a:Int,b:Int为函数形参
- 形参列表后面有一个:Int,代表函数返回Int
private fun add(a:Int,b:Int):Int{
val result = a+b
println(result)
return result
}
函数简写
当函数体只有一行代码时,可以不写括号,直接在等号后面接代码即可
private fun add(a:Int,b:Int) = println(a+b)
若函数需要返回值,则直接将计算结果接在等号后面返回
private fun add(a:Int,b:Int):Int = a+b
默认参数
fun printfInfo(name:String,age:Int) = println("I am $name and $age")
fun printfInfo(name:String="Li",age:Int) = println("I am $name and $age")
fun printfInfo(name:String="Li",age:Int=20) = println("I am $name and $age")
具名函数参数
具名参数可以任意调整实参的顺序
printfInfo(age = 10,name = "Kotlin")
...
fun printfInfo(name:String,age:Int) = println("I am $name and $age")
Unit函数
在JAVA中void为空返回类型,是一个关键字
在Kotlin中Unit是一个类类型,为函数默认返回类型
private fun exe():Unit{
    return println()
}
反引号函数
打印分数(20.22)
...
private fun `打印分数`(score:Double){
    println("分数=$score")
}
匿名函数
  val len = "Kotlin".count()
    println("len=$len")
    val len1 = "Kotlin,in".count { it->
        it == 'i'
    }
    println("len1=$len1")
隐式返回
函数声明
val printfScore:(score:Double)->String
函数实现,匿名函数无需使用return返回结果,以最后一行作为返回值进行返回
 printfScore = { it->
        println("score$it")
        "打印成功!"
    }
函数调用
 printfScore(50.50)
函数作为形参
const val NAME = "Kotlin"
const val AGE = 10
//...
JudgeInfo("Kotlin",10){ info,code->
    println("info=$info,code=$code")
 }
//...
fun JudgeInfo(name:String,age:Int,respond:(String,Int)->Unit){
    val result = name == NAME && age == AGE
    if (result == true){
        respond("success",200)
    }else{
        respond("failed",404)
    }
}
函数引用
const val NAME = "Kotlin"
const val AGE = 10
//...
JudgeInfo("Kotlin",10,::printfInfo)
 
fun printfInfo(info:String,code:Int) = println("info=$info,code=$code")
//...
fun JudgeInfo(name:String,age:Int,respond:(String,Int)->Unit){
    val result = name == NAME && age == AGE
    if (result == true){
        respond("success",200)
    }else{
        respond("failed",404)
    }
}
函数作为返回值
const val NAME = "Kotlin"
const val AGE = 10
//...
val exe = JudgeInfo()
println(exe("Kotlin",10))
 //...
fun JudgeInfo():(name:String,age:Int)->Boolean{
    return { name,age->
        val result = name ==NAME && age ==AGE
        result
    }
}
可空性
在Kotlin中不能直接给一个变量赋值null,这也极大减少了空异常频发问题
如果需要给一个变量赋null,则需要在声明时,在变量类型后面加一个?,示意准许此变量在程序中为null
val name:String ? = null
println(name)//打印出null
将一个可空类型字符串变量转为大写,需要在调用uppercase函数时前面加一个?,代表如果name不为空则执行uppercase函数,否则不执行?后面的函数
var name:String ? = null
name = "kotlin"
val msg = name?.uppercase()
println(msg)
高级函数 let
var name:String ? = null
name = "kotlin"
val msg = name?.let {
  it.uppercase()
}
println(msg)
非空断言
var name:String ? = null
name = "kotlin"
val msg = name!!.uppercase()
println(msg)
空合并操作符
var name:String ? = null
println(name ?: "name为空!")
高级函数
apply函数
- apply函数始终返回对象本身
- apply匿名函数在内部持有当前对象this
val languages = arrayOf("C++","JAVA","Kotlin","C")
    //apply函数始终返回对象本身,且apply匿名函数在内部持有当前对象this
    languages.apply {
        println("数组长度=${size}")
    }.apply {
     forEach {
         println(it)
     }
    }.apply { 
        println("遍历数组完毕")
    }
run函数
- 以最后一行作为返回值返回
- 匿名函数内部持有当前对象this
val len = languages.run {
        filter {
            it.contains('C')
        }.size
    }
 println("包含字符C的元素个数=${len}")
with函数
- 以最后一行作为返回值返回
- 匿名函数内部持有当前对象this
- 不能以拓展函数形式调用,只能将当前对象以形参形式传递
 val languages = arrayOf("C++","JAVA","Kotlin","C")
 val len = with(languages){
   filter {
           it.contains('C')
       }.size
   }
println("包含字符C的元素个数=${len}")
also函数
- also函数始终返回对象本身
- 匿名函数内部持有it
  val languages = arrayOf("C++","JAVA","Kotlin","C")
    languages.also {
       println(it.first())
    }.also {
        println(it.last())
    }.also {
        println("元素个数=${it.size}")
    }
takeIf函数
如果takeIf函数内部为true则返回对象本身,否则返回null
const val NAME = "Kotlin"
const val AGE = 10
fun main() {
    val result = JudgeInfo("Kotlin",10)
    println(result)
}
fun JudgeInfo(name:String,age:Int):String{
    return name.takeIf { name`NAME&&AGE`age } ?: "信息不匹配!"
}
takeUnless函数
takeUnless函数与takeIf函数功能相反,如果takeUnless内部为true则返回null,否则返回对象本身
集合
List
  val languages:List<String> = listOf<String>("C++","C","JAVA","Kotlin","Dart")
    // public operator fun get(index: Int): E
    //与C++的运算符重载类似
    println("第一个元素:${languages[0]}")
    languages.forEach {
        println(it)
    }
列表越界处理
//方法一
val result = languages.getOrElse(5){
        "数组越界"
    }
println(result)
//方法二
val result1 = languages.getOrNull(1000) ?: "数组越界"
println(result1)
可变List
val languages = mutableListOf("C++","C","JAVA","Kotlin","Dart")
- 删除List中包含字符C的元素
    languages.removeIf {
        it.contains('C')
    }
    languages.forEach{
        println(it)
    }
- 添加元素
通过运算符重载函数为List添加新元素
public inline operator fun MutableCollection.plusAssign(element: T) {
this.add(element)
}
    languages += "C#"
    languages += "Basic"
    languages.forEach{
        println(it)
    }
- 遍历List
forEach
languages.forEach{
    println(it)
}
for-in
 for(element in languages){
        println(element)
}
forEachIndexed
languages.forEachIndexed { index, s ->
        println("第${index+1}元素=$s")
    }
Set
不允许存在重复元素,如果存在重复元素,会自动忽略
下列输出C++ C JAVA Kotlin Dart
val languages:Set<String> = setOf<String>("C++","C","JAVA","Kotlin","Dart","C++")
    languages.forEach {
        print("$it  ")
    }
println()
元素读取
languages.elementAt(0)
防止下标越界而导致程序崩溃
//法一
val result1 = languages.elementAtOrNull(1000) ?: "越界"
//法二
val result2 = languages.elementAtOrElse(1000){
        "越界"
 }
可变Set
 val languages:MutableSet<String> = mutableSetOf<String("C++","C","JAVA","Kotlin","Dart","C++")
    languages += "Basic"
    languages -= "C++"
    languages.forEach {
        print("$it  ")
    }
数组
数组定义
val languages = arrayOf<String>("C++","C","JAVA","Kotlin","Dart","C++") //对象数组
val intNumbers = intArrayOf(1,2,3,4,5)
val doubleNumbers = doubleArrayOf(10.1,11.2,12.1)
val charArray = charArrayOf('a','b','c')
读取数组元素
 println(languages[0])
 val result1 = languages.elementAtOrElse(1000){
        "越界"
}
val result2 =languages.elementAtOrNull(1000) ?: "越界"
println(result1)
println(result2)
Map
map定义
//法一
val map:Map<String,Int> = mapOf("C" to 1,"C++" to 2,"Kotlin" to 3) 
//法二
val map1:Map<String,Int> = mapOf(Pair("C",1),Pair("C++",2),Pair("Kotlin",3))
读取map元素,如果读取map中没有的元素,则返回null
val value = map["C"]
println(value)
定义默认值
val value = map.getOrDefault("Go",-1)
println(value)
通过匿名函数定义错误读取
val value = map.getOrElse("Go"){
        "没有对应的值"
    }
 println(value)
遍历map
- 法一
val map:Map<String,Int> = mapOf("C" to 1,"C++" to 2,"Kotlin" to 3)
 map.forEach { (_, value) ->
        print("$value  ")
}
- 法二
 val map:Map<String,Int> = mapOf("C" to 1,"C++" to 2,"Kotlin" to 3)
 map.forEach {
    print("${it.value}  ")
}
- 法三
val map:Map<String,Int> = mapOf("C" to 1,"C++" to 2,"Kotlin" to 3) 
for (entry in map) {
    print("${entry.value}  ")
}
可变Map
val map:MutableMap<String,Int> = mutableMapOf("C" to 1,"C++" to 2,"Kotlin" to 3)
map += Pair("JAVA",4)
map += "Basic" to 5
map -= "C"
 map.forEach { (_, value) ->
        print("$value  ")
}
类
在Kotlin中,类的成员属性默认访问权限为public
class Student{
    var name:String = "Kotlin"
        //下列get和set默认存在
        get() = field
        set(value) {
            field = value
        }
    var sex:Char = 'm'
        get() = field.uppercaseChar()
        set(value) {
            field =value.lowercaseChar()
        }
   private var age:Int = 0
}
fun main() {
    val zhangsan = Student()
    println(zhangsan.name)
}
主构造函数
//主构造函数,下列形参为输入类型,不能直接使用,需要通过接收成为变量才能使用
class Student(name: String, age:Int){
    fun print(){
    //此处不能直接调用name
       // println(name)
    }
}
通过下列两种方式,主构造函数的形参就可以在类中使用
//法一
class Student(var name: String, var age:Int){
    fun print(){
        println(name)
    }
}
//法二
class Student(name: String, age:Int){
    var name = name
    var age = age
    fun print(){
        println(name)
    }
}
次构造函数
次构造函数必须调用主构造函数
class Student(name: String){
    var name:String = name
    var age:Int = 0
    var score:Double = 0.0
    //次构造函数必须调用主构造函数
    constructor(name: String,age:Int):this(name){
        this.name = name
        this.age = age
    }
    constructor(name: String,age:Int,score:Double):this(name){
        this.name = name
        this.age = age
        this.score = score
    }
}
fun main() {
    val lisi = Student("李四")
    val zhangsan = Student("张三",20)
    val wangwu = Student("王五",20,50.50)
    println(zhangsan.score)
}
lateinit 延迟初始化
class Student{
    lateinit var name:String
    fun initName(name:String){
        this.name = name
    }
    fun showName(){
        val flag = ::name.isInitialized//判断是否初始化
        if(flag){
            println(name)
        }else{
            println("未初始化name")
        }
    }
}
fun main() {
    println(Student().showName())
}
lazy 惰性初始化
class Student{
   //当调用的时候才初始化
    val name:String by lazy { readName() }
    private fun readName(): String {
        println("loading...")
        println("loading...")
        println("loading...")
        return "FranzLiszt"
    }
}
fun main() {
    val zhangsan = Student()
    Thread.sleep(3000)
    println(zhangsan.name)
}
继承和重载
在Kotlin中,类默认是final修饰,不能被继承;只有通过open修饰才能被继承
//类默认是final修饰,不能被继承;只有通过open修饰才能被继承
open class Person(val name:String){
    private fun printfName() = println("parent class name:$name")
    open fun showName() = println(printfName())
}
class Student(val subname:String): Person(subname){
    private fun printfName() = println("sub class name:$name")
    override fun showName()  = printfName()
}
fun main() {
    val person:Person = Student("张三")
    person.showName()
}
companion objec 伴生对象
伴生对象,与Java的Static类似,同样无论调用多少次,伴生对象只会初始化一次
class Student(){
    //伴生对象,与Java的Static类似
    companion object{
        private val name = "student"
        
        fun showName() = println(name)
    }
}
fun main() {
    println(Student.showName())
}
内部类
内部的类不能访问外部类属性,通过添加inner修饰,成为内部类才能访问
class Person(name:String){
    val name = name
    //内部的类不能访问外部类属性,通过添加inner修饰,成为内部类才能访问
    inner class Male{
        fun show() = println("male $name")
    }
    inner class Female{
        fun show() = println("female $name")
    }
}
fun main() {
    val p = Person("zs")
    p.Male().show()
}
嵌套类
嵌套类的内部的类不能访问外部类属性
class Person(name:String){
    val name = name
    class Male{
    //不能访问外部类属性
        //fun show() = println("male $name")
    }
    
    class Female{
        fun show() = println("嵌套类")
    }
}
fun main() {
    Person.Female().show()
}
数据类
定义数据类
data class Student(var name:Student,var age:Int)
反编译上面的数据类,可以看见除了成员变量的get()、set()函数外,还拓展了拷贝函数、toString()、equals()函数等;比起JAVA的JavaBean更加丰富;其中上述扩展的函数只会覆盖主构造函数的成员属性,不会覆盖次构造函数的成员属性
public final class Student {
   @NotNull
   private Student name;
   private int age;
   @NotNull
   public final Student getName() {
      return this.name;
   }
   public final void setName(@NotNull Student var1) {
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.name = var1;
   }
   public final int getAge() {
      return this.age;
   }
   public final void setAge(int var1) {
      this.age = var1;
   }
   public Student(@NotNull Student name, int age) {
      Intrinsics.checkNotNullParameter(name, "name");
      super();
      this.name = name;
      this.age = age;
   }
   @NotNull
   public final Student component1() {
      return this.name;
   }
   public final int component2() {
      return this.age;
   }
   @NotNull
   public final Student copy(@NotNull Student name, int age) {
      Intrinsics.checkNotNullParameter(name, "name");
      return new Student(name, age);
   }
   // $FF: synthetic method
   public static Student copy$default(Student var0, Student var1, int var2, int var3, Object var4) {
      if ((var3 & 1) != 0) {
         var1 = var0.name;
      }
      if ((var3 & 2) != 0) {
         var2 = var0.age;
      }
      return var0.copy(var1, var2);
   }
   @NotNull
   public String toString() {
      return "Student(name=" + this.name + ", age=" + this.age + ")";
   }
   public int hashCode() {
      Student var10000 = this.name;
      return (var10000 != null ? var10000.hashCode() : 0) * 31 + Integer.hashCode(this.age);
   }
   public boolean equals(@Nullable Object var1) {
      if (this != var1) {
         if (var1 instanceof Student) {
            Student var2 = (Student)var1;
            if (Intrinsics.areEqual(this.name, var2.name) && this.age ` var2.age) {
               return true;
            }
         }
         return false;
      } else {
         return true;
      }
   }
}
运算符重载
下列列出一些常用的重载运算符
| 表达式 | 翻译为 | 
|---|---|
| a + b | a.plus(b) | 
| a - b | a.minus(b) | 
| a * b | a.times(b) | 
| a / b | a.div(b) | 
| a % b | a.rem(b) | 
| a[i] | a.get(i) | 
| a += b | a.plusAssign(b) | 
| a > b | a.compareTo(b) > 0 | 
| a < b | a.compareTo(b) < 0 | 
| a++ | a.inc() | 
| a– | a.dec() | 
下面重写了加减乘除四个运算符,可以与C++的运算符重载做对比,差异如下
- C++直接对运算符进行重新标识,而Kotlin需要进行转化,例如重载加号运算符,需要改为plus函数
class Calculation(private val num1:Int){
    //重载加号运算符
    operator fun plus(param:Calculation):Calculation = Calculation(num1+param.num1)
    //重载减号运算符
    operator fun minus(param:Calculation):Calculation = Calculation(num1-param.num1)
    //重载乘号号运算符
    operator fun times(param:Calculation):Calculation = Calculation(num1*param.num1)
    //重载除号运算符
    operator fun div(param:Calculation):Calculation{
        if (param.num1 ` 0 )return Calculation(0)
        return  Calculation(num1/param.num1)
    }
    fun printfNum() = println("num=$num1")
}
fun main(){
    val example1 = Calculation(5)
    val example2 = Calculation(10)
    val result = example1 + example2
    result.printfNum()
}
枚举类
data class WeekInfo(var info:String)
enum class Week(private val weekInfo: WeekInfo) {
    Sunday(WeekInfo("星期天")),
    Monday(WeekInfo("星期一")),
    Tuesday(WeekInfo("星期二")),
    Wednesday(WeekInfo("星期三")),
    Thursday(WeekInfo("星期四")),
    Friday(WeekInfo("星期五")),
    Saturday(WeekInfo("星期六"));
    fun show() = println("info = ${weekInfo.info}")
    fun update(weekInfo: WeekInfo){
        this.weekInfo.info = weekInfo.info
        println("info = ${weekInfo.info}")
    }
}
fun main(){
    Week.Friday.show()
    Week.Sunday.update(WeekInfo("XINGQITIAN"))
}
代数数据类型
enum class Judge{
    Bad,
    Mid_Good,
    Superior
}
fun testScore(score: Judge): String =
    when (score) {
        Judge.Bad -> "不及格"
        Judge.Mid_Good -> "良好"
        Judge.Superior -> "优秀"
    }
fun main(){
   println(testScore(Judge.Superior))
}
密封类
sealed class Scores{
    object Fail:Scores()
    object Pass:Scores()
    object Superior:Scores()
}
fun testScore(score: Scores): String =
    when (score) {
        is Scores.Fail -> "不及格"
        is Scores.Pass -> "良好"
        is Scores.Superior -> "优秀"
    }
fun main(){
   println(testScore(Scores.Pass))
}
接口
在Kotlin中,接口实现类不仅要实现其接口的函数,还需要重写其成员变量
interface Information{
    var name:String
    var age:Int
    fun showInfo()
}
class Student(stuName:String, stuAge:Int):Information{
    override var name: String = stuName
    override var age: Int = stuAge
    override fun showInfo() {
        println("name=$name,age=$age")
    }
}
fun main(){
   val zhangsan:Student = Student("张三",20)
    zhangsan.showInfo()
}
抽象类
abstract class Base{
    fun run(){
        running(getAnimalName())
        eating(getAnimalName())
    }
    abstract fun getAnimalName():String
    abstract fun running(name:String)
    abstract fun eating(name:String)
}
class Cat:Base(){
    override fun getAnimalName(): String = "Cat"
    override fun running(name:String) = println("$name running")
    override fun eating(name:String) = println("$name eating")
    fun show(){
        super.run()
    }
}
fun main(){
   val cat:Cat = Cat()
    cat.show()
}
泛型类
class BasePrintf<T> (private val obj:T){
    fun printf() = println("输出结果:$obj")
}
data class Student(val name:String,val age:Int)
data class Teacher(val name:String,val age:Int,val id:Int)
fun main() {
    val zhangsan = Student("张三",20)
    val lisi = Teacher("李四",30,111)
    BasePrintf(zhangsan).printf()
    BasePrintf(lisi).printf()
    BasePrintf(111).printf()
    BasePrintf("aaa").printf()
}
vararg 动态参数
class Person<T>(private vararg val params:T){
    //out的作用是T只能被读取,不能修改
    private val arrays: Array<out T> = params
    fun show(index:Int): T = arrays[index]
    fun<o> map(index:Int,action:(T)->o) = action(arrays[index])
}
fun main() {
   val param = Person("Kotlin",20,false,99.99)
    println(param.show(0))
    println(param.show(1))
    param.map(3){
        println(it)
    }
}
协变&逆变
协变
- 在泛型前加out,代表此泛型只能被读取不能被修改
- 泛型的子类对象可以赋值给泛型的父类对象
interface Producer<out T>{
    fun produce():T
}
逆变
- 在泛型前加in,代表此泛型只能被修改不能被读取
- 泛型的具体父类可以赋值给泛型声明处的子类
interface Consumer<in T>{
    fun consumer(param:T)
}
扩展函数
class Student(val name:String,val age:Int)
fun Student.printf() = println("name=$name,age=$age")
fun main() {
   val zhangsan = Student("张三",20)
    zhangsan.printf()
}
单例模式
饿汉式
object Student
懒汉式
class Student{
    companion object{
        private var instance:Student ? = null
            get() {
                if (field ` null) field = Student()
                return field
            }
        fun getInstanceAction():Student = instance!!
    }
}
懒汉式-加锁
class Student{
    companion object{
        private var instance:Student ? = null
            get() {
                if (field ` null) field = Student()
                return field
            }
        @Synchronized
        fun getInstanceAction():Student = instance!!
    }
}
懒汉式-双重校验
class Student private constructor(){
    companion object{
        val instance:Student by lazy (mode =  LazyThreadSafetyMode.SYNCHRONIZED){Student()}
    }
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!