# kotlin入门

# 基本类型

# 概述

  • 数字(Byte,Short,Int,Long; Float,Double)

  • 无符号整数(Ubyte,Ushort,Uint,Ulong)

  • 布尔(Boolean,true,false)

  • 字符(Char)

  • 字符串(String)

  • 数组(Array)

类型 位宽度 说明
Byte 8 整数类型
Short 16 整数类型
Int 32 整数类型
Long 64 整数类型
Float 32 浮点数类型
Double 64 浮点数类型
Char ‘a’ 字符型,用单引号表示,不属于数值类型,不能直接与整型参与运算
Boolean true/false 布尔型
String "abc" 字符串
Array [] 数组
Ubyte 8 无符号整数类型
Ushort 16 无符号整数类型
Uint 32 无符号整数类型
ULong 64 无符号整数类型

# 数字

# 整数类型

  • Byte

  • Short

  • Int:默认

  • Long

类型 位宽 值范围
Byte 8 -128(-2的7次方)~127(2的7次方减1)
Short 16 -32768(-2的15次方)~32767(2的15次方减1)
Int 32 -2,147,483,648(-2的31次方)~2,147,483,647(2的31次方减1)
Long 64 -9,223,372,036,854,775,808(-2的63次方)~9,223,372,036,854,775,807(2的63次方减1)
/**
 * 整数的定义
 * 默认会自动推断为Int类型,当值超出Int范围时会自动推断为Long型。
 * 也可以显式指定类型
 * Long型可以用L后缀指定
 */
val one = 1 // Int
val threeBillion = 3_000_000_000 // Long
val oneSuffixL = 1L // Long
val oneByte: Byte = 1  // Byte
val oneShort: Short = 1 // Short
val oneInt: Int = 1     // Int,Int可省略
val oneLong: Long = 1   // Long

# 浮点类型

  • Float 指定f/F
  • Double 默认
类型 位宽 整数位 指数位 小数位
Float 32 24 8 6-7
Double 64 53 11 15-16
/**
 * 浮点数的定义,必须带点.
 * 超过精度会被截断,精度不准
 * 
 */
val onePointZeroDouble = 1.0 //Double
val onePointZerof = 1.0f
val onePointZeroF = 1.0F
println("onePointZero type is ${onePointZeroDouble.javaClass.name}, value is $onePointZeroDouble")
println("onePointZerof type is ${onePointZerof.javaClass.name}, value is $onePointZerof")
println("onePointZeroF type is ${onePointZeroF.javaClass.name}, value is $onePointZeroF")
// val one: Float = 1  //Error

# 数字的文字常量

  1. 不支持八进制
  2. 二进制用0b开头
  3. 十六进制用0x开头
  4. Long型由L结尾
  5. Float型由f/F结尾
  6. 支持指数(e/E)表示方式
  7. 可以添加下划线增强可读性
  • 数字(默认Int):123,12345
  • Long型:123L
  • 二进制:0b0010,0b11,0b1101
  • Double型(默认):123.0,123.4e13,123.4E13
  • Float型:123.0f,123.0F1.1236e7,1.125E5
//支持指数格式
val exponent = 1.1234e5
println(exponent)  // 112340.0
val exponent2 = 1.123477E5
println(exponent2) // 112347.7

//下划线
val underscores2 = 1_000_000
val underscores1 = 999_99_222L
val hexBytes = 0xFF_ED_23
val bytes = 0b0101_0101_1100

# JVM上的数字表示形式

  1. 两个等号比较值(等同Java的equal),三个等号比较引用(对象地址,等同Java的==)。
  2. nullable引用的值在-128~127之间,值相等时,引用也相等(由于JVM的内存优化)
  3. nullable引用的值在-128~127以外,值相等时,引用不相等。
  4. 数值装箱原则造成的影响。
  5. 字符,字符串等的比较三个等号与三个等号结果都一致
fun main(args: Array<String>){
val i1Plus127: Int? = 127
    val i2Plus127: Int? = 127

    println("i1Plus127 == i2Plus127 is ${ i1Plus127 == i2Plus127}") //true,比较值。
    println("i1Plus127 === i2Plus127 is ${ i1Plus127 === i2Plus127}") //true,比较对象地址,127永远指向同一个对象

    val i3Plus128: Int? = 128
    val i4Plus128: Int? = 128
    println("i3Plus128 == i4Plus128 is ${ i3Plus128 == i4Plus128}") //true, 比较值。
    println("i3Plus128 === i4Plus128 is ${ i3Plus128 === i4Plus128}") //false, 比较对象地址,大于127的值指向不同对象

    val i5Minus128: Int? = -128
    val i6Minus128: Int? = -128

    println("i5Minus128 == i6Minus128 is ${ i5Minus128 == i6Minus128}") //true,
    println("i5Minus128 === i6Minus128 is ${ i5Minus128 === i6Minus128}") //true

    val i7Minus129: Int? = -129
    val i8Minus129: Int? = -129

    println("i7Minus129 == i8Minus129 is ${ i7Minus129 == i8Minus129}") //true
    println("i7Minus129 === i8Minus129 is ${ i7Minus129 === i8Minus129}") //false
    
    val a1: Char? = 'a'
    val a2: Char? = 'a'
    println("a1 == a2 is ${a1 == a2}") // true
    println("a1 === a2 is ${a1 === a2}") // true

    val s1: String? = "ab"
    val s2: String? = "ab"
    println("s1 == s2 is ${s1 == s2}") // true
    println("s1 === s2 is ${s1 === s2}") // true

    val bl1: Boolean? = true
    val bl2: Boolean? = true
    println("bl1 == bl2 is ${bl1 == bl2}") // true
    println("bl1 === bl2 is ${bl1 === bl2}") // true
}

# 显式数字类型转换

  1. 数字类型之间不会自动类型转换(与Java不同)
  2. 变量需要显式进行类型转换
  3. 运算表达式中当可通过上下文推断类型时就不需要显式转换
  • toByte():Byte
  • toShort():Short
  • toInt():Int
  • toLong():Long
  • toFloat():Float
  • toDouble():Double
/**
 * @Description 显式数字转换
 * @Author 刘默远
 * @Email soul.lau0328@gmail.com
 * @Date 2023/10/10 10:37
 */
fun main(args: Array<String>) {
    integerConversions()
    floatConversions()
}

fun integerConversions() {
    val b: Byte? = 10
    val s = b?.toShort()
    val i = b?.toInt()
    val l = b?.toLong()
    val b1 = b?.toByte()
    println("$b:$s:$i:$l:$b1")
}

fun floatConversions() {
    val f: Float? = 10F
    val d = f?.toDouble()
    val f1 = d?.toFloat()
    println("$f:$d:$f1")
}

# 数字的运算

  • 支持的运算符号:加+, 减-, 乘 *, 除/ , 求余%
# 整数的除法
  • 整数的除法只返回整数部分结果,丢弃小数部分
  • 整数相除,要保留小数,则需要显式把基中一个参数转换为浮点类型
  • 与Java等同。
/**
 * 除法
 */
fun division() {
    val a = 13
    val b = 4
    val c = a / b
    println(c) // 3

    val d = a / b.toDouble() //
    println(d) // 3.25
}
# 按位运算
  1. 只能作用于IntLong
  2. 支持表达式写法(inv除外)和函数式写法
  • shl(bits) - 有符号左移,每移一位等价*2,signed shift left
  • shr(bits) - 有符号右移,每移一位等价/2,signed shift right
  • uhr(bits) - 无符号右移,每移一位等价/2,unsigned shift right
  • and(bits) - 按位与,bitwise AND
  • or(bits) - 按位或,bitwise OR
  • xor(bits)- 按位异或,bitwise XOR
  • inv() - 按位反转,即+1取反 bitwise inversion
/**
 * 按位运算
 */
fun bitwiseOperations() {
    val x = 0b0100  // 4
    val y = 0b0110 // 6
    val bits = 2
    val shl2bits = x shl bits //左移2位是16(10000)
    val shl2bits1 = x.shl(bits) //函数式写法
    println("$x(${x.toString(2)}) 左移 $bits 位是 $shl2bits(${shl2bits.toString(2)})")
    val shr2bits = x shr bits //右移2位是1
    val shr2bits1 = x.shr(bits) //函数式写法
    println("$x(${x.toString(2)}) 右移 $bits 位是 $shr2bits(${shr2bits.toString(2)})")
    val ushr2bits = x ushr bits // 无符号右移2位是1
    val ushr2bits1 = x.ushr(bits) // 函数式写法
    println("$x(${x.toString(2)}) 无符号右移 $bits 位是 $ushr2bits(${ushr2bits.toString(2)})")
    val xAndy = x and y // x与y是4(100)
    val xAndy1 = x.and(y) // 函数式写法
    println("$x(${x.toString(2)}) 与 $y(${y.toString(2)}) 是 $xAndy(${xAndy.toString(2)})")
    val xOry = x or y // x或y是6(110)
    val xOry1 = x.or(y) //函数式写法
    println("$x(${x.toString(2)}) 或 $y(${y.toString(2)}) 是 $xOry(${xOry.toString(2)})")
    val xXory = x xor y //x异或y是2(0b10)
    val xXory1 = x.xor(y) //函数式写法
    println("$x(${x.toString(2)}) 异或 $y(${y.toString(2)}) 是 $xXory(${xXory.toString(2)})")
    val inv = x.inv() // -5(-101) 只有函数式写法
    println("$x(${x.toString(2)}) 按位取反是 $inv(${inv.toString(2)})")
}
# 浮点数比较
  1. 相等检查:a == b and a != b
  2. 大小比较:a < b, a > b, a >= b,a <= b
  3. 范围实例化和范围检查:a..b,x in a..b, x !in a..b
  • 表达式比较和平常数学一样
  • 预封装函数的浮点数比较则是字面相等则等,负0.0小于0.0
  • 预封装函数的NaN等于自身
  • 预封装函数的NaN大于一切,包括大于无穷大(POSITIVE_INFINITY)
  • 预封装函数的-0.0小于0.0
/**
 * 浮点数比较
 */
fun floatPointNumbersComparision(){
    //表达式比较和平常数学一样
    println("1129.812 == 1129.8120 is "+(1129.812 == 1129.8120)) //true
    println("-0.0 == 0.0 is "+(-0.0 == 0.0)) //true
    println(Double.POSITIVE_INFINITY == Double.POSITIVE_INFINITY) //true
    println("Double.NaN == Double.NaN is "+(Double.NaN == Double.NaN)) //false NaN不与任何值相等,包括自身
    println(Double.NaN == Double.POSITIVE_INFINITY) //false
    println(Double.NaN > Double.POSITIVE_INFINITY)  //false
    println(Double.NaN < Double.POSITIVE_INFINITY)  //false

    //用预封装的方法表现不太一样,原则是字面相等即相等,负0小于0
    println(listOf(Double.NaN) == listOf(Double.NaN)) //true
    println(listOf(-0.0) == listOf(0.0)) //false
    println(listOf(Double.POSITIVE_INFINITY) == listOf(Double.POSITIVE_INFINITY)) //true
    println(listOf(13.0,-13.0,Double.NaN, Double.POSITIVE_INFINITY,-0.0,0.0).sorted()) //[-13.0, -0.0, 0.0, 13.0, Infinity, NaN]
   println(arrayOf(13.0,-13.0,Double.NaN, Double.POSITIVE_INFINITY,-0.0,0.0).sorted()) //[-13.0, -0.0, 0.0, 13.0, Infinity, NaN]
}

# 无符号整型

类型 位宽 值范围
UByte 8 0~2^8
UShort 16 0~2^16
UInt 32 0~2^32-1
ULong 64 0~2^64-1
  • u/U - 标记无符号数字
fun unsignIntegerTypes(){
    //指定类型
    val ub: UByte = 1u
    val us: UShort = 1u
    val ui: UInt = 1U
    val ul: ULong = 1U
    //明确标记为UL
    val ul1 = 1UL

    //以下自动推断类型
    val x = 13u  //uInt
    val y = 0xFFFF_FFFF_FFFFu  //ULong

}

# 布尔

  1. 取值:true, false, null
  2. 支持的操作符:!, ||, &&
  3. 操作符优先级由高到低 !, &&, ||

/**
 * 布尔类型的定义与操作
 */
private fun booleanOperation() {
    val blNull: Boolean? = null
    val blTrue = true
    val blFalse = false

//    println(!blNull) // null值不能参与运算

    println(!blTrue) //false
    println(blTrue && blFalse) //false
    println(blTrue || blFalse) //true
    //检查优先级
    println(!blTrue || blTrue) //true
    println(!blTrue && blFalse ) //false
    print(blFalse || blFalse && blTrue) //false
}

# 字符

  1. 用单引号引起来,例: 'a', '1'
  2. 支持转义字符,用 \标识,支持Unicode转义序列语法:\uFF01
  • \t - tab
  • \b - backspace
  • \n - newline(LF)
  • \r - carriage return(CR)
  • \' - single quotation mark
  • \" - double quotation mark
  • \\ - backslash(反斜杠)
  • \$ - dollar sign
private fun charDefinition() {
    val c = '1'
    val c1: Char = 'a'
    val c2 = '\u0062'
    val c3 = '\uFF01'
    println("$c$c1$c2$c3") // 1ab!
    //特殊字符
    val tab = '\t'
    val backspace = '\b'
    val n = '\n'
    val r = '\r'
    val singleQuotation = '\''
    val doubleQuotation = '\"'
    val backslash = '\\'
    val dollarSign = '\$' //直接用$也可以
    println("$tab$backspace$n$r$singleQuotation$doubleQuotation$backslash$dollarSign")

}

# 字符串

  1. 双引号引起来:"ab\$c 1$23"
  2. 字符串的字符可以通过索引访问,str[i]
  3. 字符支持for in 遍历
  4. 字符串支持 + 号连接,保证第一个元素是字符串即可
  5. 转义字符串,即单行字符串
  6. 多行字符串(支持变量,不支持转义):""" """
  7. 多行字符串输出 $ 符号要用 ${'$'}格式
/**
 * 字符串定义
 */
private fun stringDefinition(){
    val str = "ab\$c 1$23"   // ab$c 1$23
    val str1 = "abc\n123"    // abc换行123
    val str2 = "$str${str1.uppercase()}"  // ab$c 1$23ABC
    val multilineStr = """
            I am a kotliner,
        today learning definition and operation
           变量${'$'}str: $str 
           ${"as"} 
           我想换行\n支持吗?不支持啦 
           ${'$'}后面接数字字符或为空可以直接写:$1112或$
       
        好了,到这吧
    """.trimIndent()
    println(str)
    println("==========")
    println(str1)
    println("==========")
    println(str2)
    println("==========")
    println(multilineStr) //去掉最小左空格对齐原样输出
}
//result:
/**
ab$c 1$23
==========
abc
123
==========
ab$c 1$23ABC
123
==========
    I am a kotliner,
today learning definition and operation
   变量$str: ab$c 1$23 
   as 
   我想换行\n支持吗?不支持啦 
   $后面接数字字符或为空可以直接写:$1112或$

好了,到这吧
*/



/**
 * 字符串操作
 */
private fun stringOperation(){
    println("==========")
    //字符串字符的访问
    val str = "abc行云流水home"
    println(str[5]) //流
    for (c in str){
        print("$c ")
    }
}
//result
/**
==========
流
a b c 行 云 流 水 h o m e 
*/

# 数组

  1. 尽量使用集合(Collections),性能要求比较高或构建自定义结构时,才需要使用数组

  2. 使用构造器创建数组:Array

  3. 使用方法创建数组:arrayOf(), arrayOfNulls(), emptyArray()

  4. 数据可以嵌套创建多维数组

# 数组定义

//数组定义
fun arrayDifinition() {
    var words1: Array<String> = arrayOf("Paparazzi", "Junior", "Andy", "Celebrity")
    var words2: Array<String> = arrayOf("Paparazzi", "Junior", "Andy", "Celebrity")
    println(words1 == words2) //false 数组不要直接比较,无意义,永远是false
    println(words1.contentEquals(words2)) //true 数组比较用函数
    words1 += "Mofar" //添加元素 会生成一个新的数组,尽量用集合类型替代
    println(words1.joinToString())  //Paparazzi, Junior, Andy, Celebrity, Mofar

    var words3: Array<String> = Array(4) { "" } //构造函数初始化数组
    words3[0] = "Paparazzi"  //赋值
    words3[1] = "Junior"
    words3[2] = "Andy"
    words3[3] = "Celebrity"

    words3 += "Mofar" //添加元素

    println(words3.joinToString()) //Paparazzi, Junior, Andy, Celebrity, Mofar

    println(words1.contentEquals(words3)) //true

    //嵌套数组
    val twoDArray = Array(2) { Array<Int>(2) { 0 } }
    println(twoDArray.contentDeepToString()) // [[0, 0], [0, 0]]

    val threeDArray = Array(3) { Array(3) { Array(4) { 0 } } }
    println(threeDArray.contentDeepToString())
    // [[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]]
    //集合
    var collectList1 = listOf("Paparazzi", "Junior", "Andy", "Celebrity")
    var collectList2 = listOf("Paparazzi", "Junior", "Andy", "Celebrity")
    //可以==比较,表示结构内容相同promotion
    println(collectList1 == collectList2) //true
    
}

# 数组操作

  1. 访问和修改数组的元素,用 []运算符。

  2. 数组是不变的,数组的元素可变。

TODO: https://kotlinlang.org/docs/arrays.html#access-and-modify-elements

# kotlin语法

# 包声明

  • 文件以.kt为后缀。
  • 包声明与java一样,在代码文件的开头。
  • 源文件可以放在任何文件目录,与包名无关。
  • 没有指定包,则默认为default
  • 默认导入以下包
    • kotlin.*
    • kotlin.annotation.*
    • kotlin.collections.*
    • kotlin.io.*
    • kotlin.comparisons.*
    • kotlin.ranges.*
    • kotlin.sequences.*
    • kotlin.text.*

# 函数定义

  • 函数用fun关键字声明,格式: 函数名(参数1:类型, 参数n:类型):返回类型

    fun sum(a: Int, b: Int): Int { //格式: 函数名(参数:类型):返回类型
        return a + b
    }
    
  • 表达式作为函数体,返回类型自动推断

    fun sum(a: Int, b: Int) = a + b
    
  • public函数必须明确写出返回类型(无返回值除外)

    public fun sum(a: Int, b: Int): Int = a + b
    
  • 无返回值的函数用Unit表示(类似java的void),也可以省略

    fun printSum(a: Int, b: Int): Unit {
        print(a + b)
    }
    
    public fun printSum(a: Int, b: Int){
    	print(a + b)
    }
    
  • 可变长参数函数用vararg关键字标识

    fun printVar(vararg arr: Int){
        for(v in arr){
    		print("$v ")
        }
    }
    
  • lambda(匿名函数),格式:变量名:参数类型 -> 返回类型 = {参数列表 -> 函数表达式}

    fun main(args: Array<String>){
        val sumLd:(Int,Int) -> Int = {x,y -> x+y}
        print(sumLd(13,12))
    }