美文网首页
Kotlin 学习笔记(一)

Kotlin 学习笔记(一)

作者: HappyGhh | 来源:发表于2019-08-22 18:40 被阅读0次

声明:内容来自 HenCode 码上开学 的学习笔记

真心推荐,视频和文章都超级赞,非常感谢 🙏

另 附 Kotlin 学习官方文档

变量

变量声明: var关键字 变量名 :冒号 类型 结尾没有分号(对,Kotlin 里面不需要分号)
val是 Kotlin 在 Java 的「变量」类型之外,又增加的一种变量类型:只读变量。它只能赋值一次,不能修改。而 var 是一种可读可写变量。
var 是 variable 的缩写,val是 value 的缩写。

Kotlin 里面,变量没有初始值,如果声明的时候不赋值就会报错,可以用解除非空限制
所有的变量默认都是不允许为空的,如果你给它赋值 null,就会报错,

var name1: String // 👈这样写会报错,变量没有初始化
var name2: String = null // 👈这样写会报错,变量不能赋值null
var name3: String? = null //👈 正常运行 加?表示该变量是可空类型 

name3.length //「👈这样写会报错 可空类型的变量,Kotlin 不允许使用,,,Only safe (?.) or non-null asserted (!!.) calls are allowed

name3?. length // 正常运行

Kotlin 空安全设计,记住,所谓「可空不可空」,关注的全都是使用的时候,即「这个变量在使用时是否可能为空」。

变量延迟初始化

关键字lateinit修饰变量,告诉编译器我没法第一时间就初始化,但我肯定会在使用它之前完成初始化的。

类型推断, 就是在代码里不用写变量类型,编译器在编译的时候会帮你补上

var name: String = "Mike"
var name = "Mike" //可以省略变量类型String

静态属性和函数

object

Kotlin 里的 object ——首字母小写的,不是大写,Java 里的 Object 在 Kotlin 里不用了。

Java 中的 Object 在 Kotlin 中变成了 Any,和 Object 作用一样:作为所有类的基类。
而 object 不是类,像 class 一样在 Kotlin 中属于关键字.
object 的意思是,创建一个类,并且创建一个这个类的对象。可以直接理解为单例。

Java 中new 用来创建一个匿名类的对象
Kotlin 中object:也可以用来创建匿名类的对象

companion object
object 修饰的对象中变量和函数都是静态的,如果只想让类中的一部分函数和变量是静态的,那么可以在类中嵌套的对象可以用companion 修饰

top-level property / function 声明

除了静态函数这种简便的调用方式,Kotlin 还有更方便的东西:「top-level declaration 顶层声明」。其实就是把属性和函数的声明不写在 class 里面,

package com.hencoder.plus
​
// 👇 属于 package,不在 class/object 内
fun topLevelFuncion() {
}

这样写的属性和函数,不属于任何 class,而是直接属于 package,它和静态变量、静态函数一样是全局的,但用起来更方便:你在其它地方用的时候,就连类名都不用写

在实际使用中,在object、companion objecttop-level 中该选择哪一个呢?简单来说按照下面这两个原则判断:

如果想写工具类的功能,直接创建文件,写 top-level「顶层」函数。
如果需要继承别的类或者实现接口,就用 object 或 companion object。

常量

Kotlin 中声明常量用关键字const
Kotlin 的常量必须声明在对象(包括伴生对象)或者「top-level 顶层」中,因为常量是静态的。
Kotlin 中只有基本类型和 String 类型可以声明成常量. 原因是 Kotlin 中的常量指的是 「compile-time constant 编译时常量」,它的意思是「编译器在编译的时候就知道这个东西在每个调用处的实际值」,因此可以在编译时直接把这个值硬编码到代码里使用的地方。
而非基本和 String 类型的变量,可以通过调用对象的方法或变量改变对象内部的值,这样这个变量就不是常量了。

函数

函数声明:fun关键字 方法名(参数..) 冒号 返回值类型{ 函数体 }

如果没有返回值 可以用 Unit ,也可以直接省略。 如果函数体只有一行代码可以直接用=不需要用{}

fun sum(a: Int, b: Int) = a + b //返回值类型也可以自动推断
//完全一样的两个函数
fun sum(a: Int, b: Int): Int {
        return a + b
    }
// 参数有默认值的函数
fun sum1(a: Int = 0, b: Int = 0): Int {
        return a + b
    }

Kotlin 函数参数默认是 val 类型,所以参数前不需要写 val 关键字,Kotlin 里这样设计的原因是保证了参数不会被修改,而 Java 的参数可修改(默认没 final 修饰)会增加出错的概率。

本地函数(嵌套函数)

类型

基本类型:数字(Byte、Short、Int、Long、Float、Double)、字符(Char)、布尔值(Boolean)、数组(Array)与字符串(String)

var number: Int = 1 // 👈还有 Double Float Long Short Byte 都类似
var c: Char = 'c'
var b: Boolean = true
var array: IntArray = intArrayOf(1, 2) // 👈类似的还有 FloatArray DoubleArray CharArray 等,intArrayOf 是 Kotlin 的 built-in 函数
var str: String = "string"

在Kotlin中,较小类型不是较大类型的字类型,所以不能显式类型转换。

var b : Byte = 1
var number: Int = b// 👈错误,无法进行显式转换
var number: Int = b.toInt() // 正常运行

字符串

当字符串较多的时候,Java给出的解决方案是String.format Kotlin 中,用$加参数,不仅可以跟变量,还可以跟表达式,但表达式是一个整体,需要用{} 包起来。

trimMargin()函数可以去除每行前面的空格

val text = """
     👇 
      |Hi world!
    |My name is kotlin.
""".trimMargin()
println(text)

注意:|符号为默认的边界前缀,前面只能有空格,否则不会生效
输出时|符号以及它前面的空格都会被删除
边界前缀还可以使用其他字符,比如 trimMargin("/"),只不过上方的代码使用的是参数默认值的调用方式

数组和集合

Kotlin 和 Java 一样有三种集合类型:List、Set 和 Map,它们的含义分别如下:

List 以固定顺序存储一组元素,元素可以重复。
Set 存储一组互不相等的元素,通常没有固定顺序。
Map 存储 键-值 对的数据集合,键互不相等,但不同的键可以对应相同的值。

三种集合创建可变和不可变的例子:

listOf()创建不可变的ListmutableListOf() 创建可变的 List
setOf()创建不可变的 SetmutableSetOf() 创建可变的Set
mapOf() 创建不可变的 MapmutableMapOf() 创建可变的 Map

可以看到,有 mutable前缀的函数创建的是可变的集合,没有 mutbale 前缀的创建的是不可变的集合,不过不可变的可以通过 toMutable*()系函数转换成可变的集合:

val strList = listOf("a", "b", "c")
            👇
strList.toMutableList()
val strSet = setOf("a", "b", "c")
            👇
strSet.toMutableSet()
val map = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 3)
         👇
map.toMutableMap()

注意:toMutable*() 返回的是一个新建的集合,原有的集合还是不可变的,所以只能对函数返回的集合修改。

Sequence
Kotlin 还引入了一个新的容器类型 Sequence,和 Iterable 一样用来遍历一组数据并可以对每个元素进行特定的处理.

类和对象

Kotlin 的类默认是 public 的,类的继承和实现都用:,构造函数用关键字constructor和其他函数fun进行区分。 Kotlin 中关键字override函数的可见性继承自父类

class MainActivity constructor()

类的主构造器

class User constructor(name: String) {
    //                  👇 这里与构造器中的 name 是同一个
    var name: String = name
}

kotlin中一个类最多能有一个主构造器(可以没有),次构造器的个数没有限制。
java中一个类最多能有一个空构造函数(可以没有)。。是不是感觉很熟悉 哈哈哈

主构造器中的参数除了可以用作类的属性,还可以在init代码块中使用,init代码块是紧跟在主构造器之后执行的,因为主构造器没有带马蹄,init代码块就充当类主构造器代码体的功能。

如果在主构造器的参数声明时加上 var 或者 val,就等价于在类中创建了该名称的属性(property),并且初始值就是主构造器中该参数的值。

如果类中有主构造器,那么次构造器要通过this关键字调用主构造器,可以直接调用也可通过其他构造器间接调用,不管怎样,必须调用,否则会报错。

class User constructor(var name: String) {
                                   // 👇  👇 直接调用主构造器
    constructor(name: String, id: Int) : this(name) {
    }
                                                // 👇 通过上一个次构造器,间接调用主构造器
    constructor(name: String, id: Int, age: Int) : this(name, id) {
    }
}

通常情况下,主构造器中的constructor关键字是可以省略的,但是,当主构造器使用 「可见修饰符」或者「注解」的时候是不可以省略的

class User private constructor(name: String) {
//           👆 主构造器被修饰为私有的,外部就无法调用该构造器
}

类型判断与强转

Kotlin 中使用 is 关键字进行「类型判断」,不判断直接强制转换使用关键字as,
如果强转类型错误程序会报异常用as?来处理这种情况,如果转换失败则不调用,转换成功才调用。

相关文章

网友评论

      本文标题:Kotlin 学习笔记(一)

      本文链接:https://www.haomeiwen.com/subject/eavbsctx.html