【Kotlin】学习小记-基础篇

这是一份大概的kotlin学习目录纪要,大部分内容摘自自学时的笔记。内容不够完全,有需要详细了解的地方,还需要自己单独去查阅。主要是供给android开发人员由Java转kotlin的码畜们。

在这里插入图片描述

附上一份android进阶的思维导图,无论是学习还是巩固,供参考。
在这里插入图片描述

Kotlin的介绍

在这里插入图片描述

注:本文为自学笔记,仅供参考,内容是自己根据自己的情况来进行标注着重点的。欢迎各位多多指教~

kotlin它是基于JVM的编程语言,它可以编译成java字节码,也可以编译成javaScript,方便在没有JVM的设备上运行。

关于kotlin的特点介绍如下两点:

  1. kotlin和Java可以互调使用 让你的项目可以根据需要,自由切换两种语言的使用;
  2. kotlin是一门函数式编程语言
  3. 减少崩溃,提升体验:

    可以通过在 Java 代码中使用 @Nullable 和 @NonNull 等注解来确保 Kotlin 代码获得正确的可空性推断
    整体上看,Kotlin 的空安全特性帮助点评 Android 应用将空指针导致的崩溃从日均 3 个降低至 0。
    Google Play 排名前 1,000 的应用,发现使用 Kotlin 的应用与不使用 Kotlin 的应用相比,其用户崩溃率低20%

入门基础篇

属性声明

声明属性:var和val
var:可变变量;声明的属性可以有getter,setter方法。

var nickName:String="Max"
fun changeValue2(){
        nickName="Sherry"
}

操作:将nickeName变量从值Max修改为Sherry 结果:执行成功。

val:只读变量;声明的属性只有gette方法;类似于java中的final变量;它在创建时必须初始化,以后不可修改。

val sex:String="Female"
fun changeValue(){
        sex="Male"
}

操作:将sex只读变量从Female变为Male 结果:报错Val cannot be reassigned 
结论:val是只读变量,赋值后不可修改

在实际开发中,定义变量的时候,你会发现,kotlin不允许未初始化的变量。如何解决?
lateinit 延迟初始化变量。值得注意的是,使用该变量的时候,要确保其不为null。

lateinit var name:String
    
    fun way(){
        print(name)
    }
关于val和final的小Tips

在java中使用final修饰的参数,在kotlin中函数参数可以不用写val关键字,因为它默认就是final修饰符。

参数

1.可变参数

用vararg修饰参数,kotlin的可变参数一般是函数的最后一个参数

fun <T> toList(vararg items:T):List<T>{
        val result=ArrayList<T>()
        for (item in items){
            result.add(item)
        }
        return result
 }

 fun main(arrays:Array<String>){
        val list=toList("java","kotlin","python","scala")
        println(list)
 }

在toList里面也可以直接放入数组。
step1:建立数组,存入内容
step2:调用toList(*array)。
在stpe2里面,参数名array前面多了一个 * 号。它表示解包数组,能够让每个数组中的每个元素在函数中被作为单独的参数

fun main2(arrays: Array<String>){
        val array= arrayOf("java","kotlin","python","scala")
        val list=toList(*array)
        print(list)
}
2.命名参数

sum函数内有两个参数,x=0的一个默认参数,参数y。
在调用函数时,命名参数则是y=1,为y指定参数的值。

fun sum(x:Int=0,y:Int):Int{
        return x+y
}

fun test(){
        sum(y=1)  //相当于 sum(0,1)
}

当y值使用默认值时:

fun sum(x:Int=0,y:Int=2,z:Int=1):Int{
        return x+y+z
    }

fun test(){
        sum(1,z=5) //类似于sum(1,2,5)
}

函数返回值

接接接下来,就是我们kotlin很重要的一个part了,什么事孤独终老…呸呸呸!函数的part!
在这里插入图片描述

1.默认返回Unit值

关于kotlin内函数的返回,它没有java中的void,但是函数始终默认会返回一个Unit类型。

fun test1():Unit{
        println("Hello")
}

Unit返回值可以被省略:

fun test1(){
        println("Hello")
}
2.返回Nothing值情况
fun forNothing():Nothing{
        while (true){
            println("do nothing")
        }
    }

fun mainNothing(){
        forNothing()
        println("run here?")
}

结果:
do nothing
结果里并没有打印 run here? 所以如果返回值为 Nothing ,则Nothing表达式之后的所有代码都不会执行。

函数表达式

1.单表达式函数
fun sum1(x:Int=0,y:Int):Int{
        return x+y
}

当函数为单个表达式时,可以省略函数体的花括号。
等价于:

fun sum1(x:Int,y:Int):Int=x+y

也等价于:

fun sum1(x:Int,y:Int)=x+y

它根据编译器推断函数的返回类型。

2.成员函数

在类或对象内部定义的函数。这点和java一致。

3.局部函数

指在一个函数中去定义另一个函数,类似于内部类。
局部函数可以访问外部的局部变量,甚至闭包

4.尾递归函数

在kotlin中实现尾递归的条件:
1.使用tailrec关键字。 使用该关键词后,编译器会优化该递归,从而避免堆栈溢出的问题。
2.在函数最后进行递归调用

接下来;
kotlin的类和java中的类,这东西就是,横看成岭侧成峰,远近高低各不同,来吧,看看是峰还是林。
在这里插入图片描述

1.抽象类

含有抽象方法的类,为抽象类。这一点和java的概念一致。

2.嵌套类和内部类

嵌套类:定义在某一个类内部的类。嵌套类不能访问外部类的成员,除非嵌套类变成内部类。

class OuterClass{
        val str:String="this is a outer"

        class Nested{
            fun foo()= println("")
        }
    }
    
fun main(args:Array<String>){
        OuterClass.Nested().foo()
}

内部类:

class Outter2{
        val str:String="this is property outter"
        inner class Inner{
            fun foo()= println("$str")
        }
    }

fun main(args: Array<String>){
        Outter2().Inner().foo()
}
3.枚举类

kotlin的枚举条件:enum和class关键字

enum class Color constructor(var colorName:String,var value:Int){
        RED("红色",1),GREEN("绿色",2),BLUE("蓝色",3)
}

枚举类的属性不需要写在枚举类内部,每个枚举都是枚举类的实例。

构造函数和初始化块

kotlin的构造函数可以包括,一个主构造函数+N个次构造函数

初始化块

init块作为初始化块的前缀。

看到这里是不是你有些累了?那…看一篇舔狗日记,来放松一下吧。继续往下走
在这里插入图片描述

主构造函数
class Constructor2 constructor(){
        init {
            println("test constructor2")
        }
}

在此代码中,constructor作为构造函数的函数名,此时可省略函数名。

省略后的代码如下:

class Constructor2{
        init {
            print("test constructor2")
        }
}

+ 主构造函数可以省略constructor关键字,无论主构造器是否包含有参数

class Constructor2 constructor(){
        init {
            println("test constructor2")
        }

        init {
            println("test init2")
        }

        init {
            println("test init3")
        }
}

执行结果:

test constructor2
test init2
test init3

+ 初始化块有多个,调用主构造函数时会按照初始化块的顺序执行。

次构造函数

+ 次构造函数,使用constructor作为函数名,但不能省略函数名。
+ 次构造函数调用之前必须调用主构造函数,次构造器函数可以包含代码。

   /**
     * 次构造函数
     */
    class Constructor4(str:String){
        init {
            println("$str")
        }
        
        //this(str1) 调用主构造函数以及它的初始化块
        constructor(str1:String,str2:String):this (str1){
            println("$str1"+"$str2")
        }
        
        fun foo()= run { println("this is foo function!") }
    }
    
    fun mainConstructor4(args:Array<String>){
        val obj=Constructor4("testConstructor4.1","testConstructor4.2")
        obj.foo()
    }

执行结果:

testConstructor4.1
testConstructor4.1 testConstructor4.2
this is foo function

次构造函数的特点:
+ 主构造函数的属性可以使用var,val修饰,次构造函数不能用这些修饰。
+ 次构造函数需要依托给主构造函数,调用次构造函数时会先调用主构造函数以及初始化块。

对象声明

在这里插入图片描述
Object关键字修饰对象:
通过对象声明可以实现单例模式

object Singleton{
        fun printSingleton()= println("just println singleton")
}

fun main(args: Array<String>){
        println(Singleton.printSingleton())
}

将如上代码进行反编译,我们可以看到对象声明类似于 饿汉模式。

它是延迟初始化的,只有当第一次使用printSingleton()方法时,Singleton才会初始化。

对象表达式

它类似于Java中的匿名内部类。

tv_main_click.setOnClickListener(object :View.OnClickListener{
            override fun onClick(p0: View?) {
                println("print max's hello")
            }

})

它相对于java的匿名内部的特点如下:
+ 支持实现多个接口
+ 可访问非final修饰的变量

伴生对象(Companion Object)

kotlin中没有静态属性和静态方法,我们用Companion Object来解决它这一问题。简而言之,它就是代替Java中的static。
伴生对象初始化的时间是:类加载时初始化

class PersonInfo{
        companion object{
            private var name:String="Max"
            private var age=20
            private var color="blue"
            
            fun changeLikeColor(color:String){
                this.color=color
            }

            fun printColor(){
                println("This $this.name is $this.age and she like $this.color")
            }

        }
    }

    fun main(args: Array<String>){
        PersonInfo.changeLikeColor("black")
        println(PersonInfo.printColor())

        PersonInfo.changeLikeColor("orange")
        println(PersonInfo.printColor())
    }

运行结果:

This Max is 20 and she like black
This Max is 20 and she like orange

Kotlin里特别的类

在这里插入图片描述

数据类(Data class)

Data数据类型,它是由final修饰的类型,不可被继承。

data class TestData(var name:String)
data class TestUser(var name:String,var password:String,var testData:TestData)

fun main(args: Array<String>){
        var user1=TestUser("Max","123456", TestData("TestDataUserInfo1"))

        var user2=user1.copy()
        println(user2)

        //判断data class的copy是否为浅拷贝.若二者的address指向的内存地址相同,说明data的copy为浅拷贝,否则为深拷贝。
        println(user2.testData===user1.testData)

        var user3=user1.copy("Caroline")
        println(user3)

        var user4=user1.copy(password = "asdfgh")
        println(user4)
    }

执行结果为:

true
TestUser(name=Caroline, password=123456, testData=TestData(testData=TestDataUserInfo1))
TestUser(name=Frank, password=asdfgh, testData=TestData(testData=TestDataUserInfo1))

tips:===比较的是内存地址

密封类(Sealed class)

密封类一般和when语句搭配使用,从功能上而言,更类似于枚举。

sealed class Normal(val name:String)

class Dog(dogName:String):Normal(dogName)
class Cat(catName:String):Normal(catName)
class Deer(deerName:String,val color:String):Normal(deerName)

fun greetNormal(normal:Normal)= when (normal){
    is Dog->"print ${normal.name}"
    is Cat->"print ${normal.name}"
    is Deer->"print ${normal.name} the color is ${normal.color}"
}

fun main(array: Array<String>){
    println(greetNormal(Dog("发财")))
    println(greetNormal(Cat("恭喜")))
    println(greetNormal(Deer("flash","yellow")))
}

执行结果:

print 发财
print 恭喜
print flash the color is yellow

密封类特点:
密封类是一个抽象类
密封类的所有子类要么在密封类中,要么跟密封类在同一文件中,密封类的子类的子类,可在任意位置。
若和when语句联合使用时,is语句可涵盖所有的情况,则无需添加else语句。

以上的内容为kotlin很基础的入门篇,对我来说,很重要的就是对于函数的使用部分,对象声明对于单例模式的实现的理解使用。
后续若有新知识get到,那就随缘更新吧。

下一篇进阶篇的文章链接奉上:Kotlin学习小记之进阶篇(一)
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值