0
点赞
收藏
分享

微信扫一扫

Kotlin语言-基础

Ad大成 2022-03-30 阅读 105
java

目录

一.基础

1.1程序入口

1.2函数定义

1.3定义常量与变量

1.4字符串模板

1.5空值检测

1.6使用区间

1.7类型检测与自动类型转换

二.函数

2.1.run,let和apply

2.2with函数

2.3takeif和takeUnless

2.4 if

2.5 for循环

 2.6while循环

2.7when表达式

2.8返回和跳转 

四.集合

4.1list基础使用

4.2 不可变集合和可变集合

4.3mutator和removeIf

4.4集合遍历

4.5set基础使用

4.6list和set的转换

4.7数组

4.8 map

4.9 map的遍历

4.10可变的map

五.类

5.1类和实例

5.2构造函数(主构造函数和次构造函数)

5.3继承

5.4抽象类

5.5嵌套类

5.6内部类

5.7接口 

5.8枚举类

5.9数据类

5.10泛型

一.基础

1.1程序入口

fun main() {
println("Hello world!")
}

1.2函数定义

函数定义使用关键字 fun,参数格式为:参数 : 类型

fun sum(a: Int, b: Int): Int {   // Int 参数,返回值 Int
return a + b
}

 无返回值的函数(类似Java中的void),Unit 返回类型可以省略。

fun printSum(a: Int, b: Int): Unit {
println("sum of $a and $b is ${a + b}")
}

1.3定义常量与变量

定义只读局部变量使用关键字 val 定义。只能为其赋值一次。(类似Java中final修饰的变量)

可变变量定义:var 关键字

val a: Int = 1
val b = 1 // 系统自动推断变量类型为Int
val c: Int // 如果不在声明时初始化则必须提供变量类型
c = 1 // 明确赋值


var x = 5 // 系统自动推断变量类型为Int
x += 1 // 变量可修改

1.4字符串模板

$ 表示一个变量名或者变量值

$varName 表示变量值

${varName.fun()} 表示变量的方法返回值:

1.5空值检测

当可能用 null 值时,必须将引用显式标记为可空。可空类型名称以问号(?)结尾

//类型后面加?表示可为空
var age: String? = "23"


//如果 str 的内容不是数字返回 null:
fun parseInt(str: String): Int? {
// ……
}

1.6使用区间

使用 in 操作符来检测某个数字是否在指定区间内。

for (i in 1..4) print(i) // 输出“1234”

1.7类型检测与自动类型转换

is 或者其否定形式 !is操作符检测一个表达式是否某类型的一个实例。 如果一个不可变的局部变量或属性已经判断出为某类型,那么检测后的分支中可以直接当作该类型使用,无需显式转换,类似于Java中的instanceof关键字)。

二.函数

2.1.run,let,apply和also

run:

  1. 调用同一个对象的多个方法 / 属性时,可以省去对象名重复,直接调用方法名 / 属性即可
  2. 定义一个变量在特定作用域内
  3. 统一做判空处理
object.run{
// ...
}
// 返回值 = 函数块的最后一行 / return表达式

let:

// 作用1:使用it替代object对象去访问其公有的属性 & 方法
object.let{
it.todo()
}

// 作用2:判断object为null的操作
object?.let{//表示object不为null的条件下,才会去执行let函数体
it.todo()
}

// 注:返回值 = 最后一行 / return的表达式

 

apply:

  • apply函数返回传入的对象的本身

also:

返回值 = 传入的对象的本身

// also函数
var result = mVar.also {
it.function1()
it.function2()
it.function3()
999
}
// 最终结果 = 返回一个mVar对象给变量result

 

2.2with函数

作用:调用同一个对象的多个方法 / 属性时,可以省去对象名重复,直接调用方法名 / 属性即可

 with(object){
// ...
}

// 返回值 = 函数块的最后一行 / return表达式

2.3takeif和takeUnless

takeIf  :   接收一个判断条件表达式,如果判断表达式为true则返回 对象本身,false返回 null

takeUnless:  与takeIf相反,  如果判断表达式为true则返回 null,false返回 对象本身

2.4 if

if 是一个表达式:它会返回一个值。 因此就不需要三元运算符(条件 ? 然后 : 否则),因为普通的 if 就能胜任这个角色。

//sampleStart
fun maxOf(a: Int, b: Int) = if (a > b) a else b
//sampleEnd

fun main() {
println("max of 0 and 42 is ${maxOf(0, 42)}")
}

2.5 for循环

语法如下:for (item in collection) print(item)

fun main() {
//sampleStart
val items = listOf("apple", "banana", "kiwifruit")
for (item in items) {
println(item)
}
//sampleEnd
}

 2.6while循环

fun main() {
//sampleStart
val items = listOf("apple", "banana", "kiwifruit")
var index = 0
while (index < items.size) {
println("item at $index is ${items[index]}")
index++
}
//sampleEnd
}

2.7when表达式

when 类似其他语言的 switch 操作符

在 when 中,else 同 switch 的 default。如果其他分支都不满足条件将会求值 else 分支。

//sampleStart
fun describe(obj: Any): String =
when (obj) {
1 -> "One"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "Not a string"
else -> "Unknown"
}
//sampleEnd

fun main() {
println(describe(1))
println(describe("Hello"))
println(describe(1000L))
println(describe(2))
println(describe("other"))
}

如果很多分支需要用相同的方式处理,则可以把多个分支条件放在一起,用逗号分隔:

when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}

2.8返回和跳转 

  • return。默认从最直接包围它的函数或者匿名函数返回。
  • break。终止最直接包围它的循环。
  • continue。继续下一次最直接包围它的循环。
fun main(args: Array<String>) {
for (i in 1..10) {
if (i==3) continue // i 为 3 时跳过当前循环,继续下一次循环
println(i)
if (i>5) break // i 为 6 时 跳出循环
}
}

四.集合

4.1list基础使用

尽量使用getOrElse或者getOrNull,避免出现越界

fun main(){
var list : List<String> = listOf("xiaoxie","xiaofei","xiaozhou","xiaozhi")

//打印字符串
println(list[0])
//getOrElse
println(list.getOrElse(4){"越界了"})//返回越界了
//getOrNull
println(list.getOrNull(4))//返回null
}

4.2 不可变集合和可变集合

不可变集合转化成可变集合:使用toMutableList()
可变集合转化成不可变集合:使用toList()
fun main(){

var list= listOf<String>("xiaoxie","xiaofei","xiaozhou","xiaozhi")

//不可变集合转化成可变集合
var mulist1=list.toMutableList()
mulist1.add("xiaozhao")
mulist1.remove("xiaozhi")

//可变集合转化成不可变集合
var mulist2= mutableListOf<String>("xiaoxie","xiaofei","xiaozhou","xiaozhi")
var list2=mulist2.toList()

}

4.3mutator和removeIf

mutator包括+= 和-= 用法

removeIf用法:当{}为true时,则移除对应的元素

fun main(){

val list= mutableListOf<String>("xiaoxie","xiaofei","xiaozhou","xiaozhi")
list += "xiaoxiao"
list -= "xiaozhou"
println(list)//打印出[xiaoxie, xiaofei, xiaozhi, xiaoxiao]

list.removeIf { it.contains("xiaozhi") } //如果等于xiaozhi,则remove掉
println(list)//[xiaoxie, xiaofei, xiaoxiao]
}

4.4集合遍历

三种遍历方式:forEach,forEachIndexed和for

fun main(){

val list= listOf<String>("xiaoxie","xiaofei","xiaozhou","xiaozhi")
//遍历的三种用法
for (i in list){
println("元素:$i")
}
//foreach
list.forEach{
println("元素:$it")
}

//下标和元素
list.forEachIndexed { index, s ->
println("下标是$index,元素是$s")
}
}

4.5set基础使用

fun main(){
val set= setOf<String>("xiaoxie","xiaofei","xiaozhou","xiaozhi")

//获取元素
println(set.elementAt(0))

//尽量使用此种方式,防止数据越界
println(set.elementAtOrElse(4){"越界了"})//打印越界了
//
println(set.elementAtOrNull(4))//打印出null
}

可变的set:

var set1= mutableSetOf<String>("xiaoxie","xiaofei","xiaozhou","xiaozhi")

其他使用同list一样

4.6list和set的转换

fun main(){
val list= mutableListOf<String>("xiaoxie","xiaofei","xiaozhi","xiaozhi")

//list转化成set
val set=list.toSet()
println(set)//[xiaoxie, xiaofei, xiaozhi]

//list转化成set,在转化成list
val list1=list.toSet().toList()
println(list1)//[xiaoxie, xiaofei, xiaozhi]

//快捷函数去重
val list2=list.distinct()
println(list2)//[xiaoxie, xiaofei, xiaozhi]

}

4.7数组

fun main(){

val intArray= intArrayOf(1,2,3,4,5,6)
println(intArray[0])//1
//获取数组的元素
println(intArray.elementAtOrElse(0){-1})//1
println(intArray.elementAtOrElse(6){-1})//-1
//list转数组
val charArray= listOf('A','B','C').toCharArray()
println(charArray)//ABC

}

4.8 map

fun main(){
val map1:Map<String,String> = mapOf("xiaoxie" to ("xiaofei"),"xiaozhou" to ("xiaozhi"))

val map2 = mapOf(Pair("xiaoxie","xiaofei"), Pair("xiaozhou","xiaozhi"))

//获取value值,建议使用
println(map1["xiaoxie"])//xiaofei
//通过key查找,找不到,返回null
println(map1["xiaoxiao"])//null

//getOrDefault方式
println(map2.getOrDefault("xiaoxie","cc"))//xiaofei
println(map2.getOrDefault("xiaoxiao","cc"))//cc

//getOrElse
println(map2.getOrElse("xiaoxie"){"xx"})//xiaofei
println(map2.getOrElse("xiaoxiao"){"xx"})//xx

//getValue,不建议使用
println(map2.getValue("xiaoxie"))//xiaofei
println(map2.getValue("xiaoxiao"))//提示.NoSuchElementException

}

4.9 map的遍历

fun main(){
val map1:Map<String,String> = mapOf("xiaoxie" to ("xiaofei"),"xiaozhou" to ("xiaozhi"))

//第一种方法
map1.forEach{
println("k:${it.key},V:${it.value}")
}

//第二种方法
map1.forEach { key:String,value:String->
println("k:$key,v:$value")
}

//第三种方法
map1.forEach{(key,value)->
println("key:$key,value:$value")
}

//第四种方法
for (entry in map1){
println("key:${entry.key},value:${entry.value}")
}
}

4.10可变的map

fun main() {
val map = mutableMapOf("xiaoxie" to ("xiaofei"), "xiaozhou" to ("xiaozhi"))

//一般操作
map += "xiaoxiao" to "cici"
map["xiaoxi"]="xixi"
map.put("xiaoyu","cc")
println(map)//{xiaoxie=xiaofei, xiaozhou=xiaozhi, xiaoxiao=cici, xiaoxi=xixi, xiaoyu=cc}


//如果map里没有heihei这个key,则添加进去map,且value值是xixixi
val r=map.getOrPut("heihei"){"xixixi"}
println(map)//{xiaoxie=xiaofei, xiaozhou=xiaozhi, xiaoxiao=cici, xiaoxi=xixi, xiaoyu=cc, heihei=xixixi}

//如果map里有xiaoyu这个key,则获取原有的value值
val r1=map.getOrPut("xiaoyu"){"xixixi"}
println(map)//{xiaoxie=xiaofei, xiaozhou=xiaozhi, xiaoxiao=cici, xiaoxi=xixi, xiaoyu=cc, heihei=xixixi}



}

五.类

5.1类和实例

类的属性可以用关键字 var 声明为可变的,否则使用只读关键字 val 声明为不可变。

class Rectangle(var height: Double, var length: Double) {
var perimeter = (height + length) * 2
}

创建实例:val site = Rectangle() // Kotlin 中没有 new 关键字

使用一个属性,只要用名称引用它即可:site.name // 使用 . 号来引用

5.2构造函数(主构造函数和次构造函数)

在 Kotlin 中的一个类可以有一个主构造函数以及一个或多个次构造函数。主构造函数是类头的一部分:它跟在类名与可选的类型参数后。

class Person constructor(firstName: String) { /*……*/ }

如果主构造函数没有任何注解或者可见性修饰符,可以省略这个 constructor 关键字。

主构造器中不能包含任何代码,初始化代码可以放在初始化代码段中,初始化代码段使用 init 关键字作为前缀。

class Person constructor(firstName: String) {
init {
println("FirstName is $firstName")
}
}

类也可以有二级构造函数,需要加前缀 constructor:

class Person { 
constructor(parent: Person) {
parent.children.add(this)
}
}

 

5.3继承

所有类都继承该 Any 类,它是所有类的超类

类之间继承由冒号(:)声明。默认情况下类都是 final 的;如需让一个类可继承, 请将其标记为 open

open class Shape

class Rectangle(var height: Double, var length: Double): Shape() {
var perimeter = (height + length) * 2
}

5.4抽象类

xxx

5.5嵌套类

class Outer {                  // 外部类
private val bar: Int = 1
class Nested { // 嵌套类
fun foo() = 2
}
}

fun main(args: Array<String>) {
val demo = Outer.Nested().foo() // 调用格式:外部类.嵌套类.嵌套类方法/属性
println(demo) // == 2
}

5.6内部类

内部类使用 inner 关键字来表示。

内部类会带有一个对外部类的对象的引用,所以内部类可以访问外部类成员属性和成员函数。

class Outer {
private val bar: Int = 1
var v = "成员属性"
/**嵌套内部类**/
inner class Inner {
fun foo() = bar // 访问外部类成员
fun innerTest() {
var o = this@Outer //获取外部类的成员变量
println("内部类可以引用外部类的成员,例如:" + o.v)
}
}
}

fun main(args: Array<String>) {
val demo = Outer().Inner().foo()
println(demo) // 1
val demo2 = Outer().Inner().innerTest()
println(demo2) // 内部类可以引用外部类的成员,例如:成员属性
}

5.7接口 

使用 interface 关键字定义接口,允许方法有默认实现

interface MyInterface {
fun bar() // 未实现
fun foo() { //已实现
// 可选的方法体
println("foo")
}
}

实现接口

class Child : MyInterface {
override fun bar() {
// 方法体
}
}

 

5.8枚举类

enum class Direction {
NORTH, SOUTH, WEST, EAST
}

5.9数据类

数据类 并以 data 标记,类似于java中的POJO

data class User(val name: String, val age: Int)

数据类必须满足以下要求:

  • 主构造函数需要至少有一个参数。
  • 主构造函数的所有参数需要标记为 val 或 var
  • 数据类不能是抽象、开放、密封或者内部的。

 

5.10泛型

class Box<T>(t: T) {
var value = t
}

创建这样类的实例只需提供类型参数即可:

val box: Box<Int> = Box<Int>(1)
fun main(args: Array<String>) {
val age = 23
val name = "runoob"
val bool = true

doPrintln(age) // 整型 整型数字为 23

doPrintln(name) // 字符串 字符串转换为大写:RUNOOB

doPrintln(bool) // 布尔型 T 不是整型,也不是字符串
}

fun <T> doPrintln(content: T) {

when (content) {
is Int -> println("整型数字为 $content")
is String -> println("字符串转换为大写:${content.toUpperCase()}")
else -> println("T 不是整型,也不是字符串")
}
}

 

泛型函数:

fun <T> singletonList(item: T): List<T> {
// ……
}

调用的话,在调用处函数名之后指定类型参数即可:

val l = singletonList<Int>(1)

 

举报

相关推荐

0 条评论