Kotlin学习-内置类型

310 阅读6分钟

一、基本类型

1、类型

类型Kotlin定义Java定义(含包装类型)
字节Bytebyte/Byte
整型Int&Longint/Integer&long/Long
浮点型Float&Doublefloat/Float&double/Double
字符Charchar/Character
字符串StringString

Kotlin的类型还分为有符号类型和无符号类型

数据类型有符号类型无符号类型
字节ByteUByte
短整型ShortUShort
整型IntUInt
长整型LongULong
字符串StringString

2、声明变量

(1)val只读变量,var可读可写变量。注意val定义的不能叫做常量,因为比如下面的例子val的值就是可变的,只是不能被外部赋值修改:

class MainActivity : AppCompatActivity() {
    
    val b: Int  //虽然b不能被修改,但是每次取b的值都是不一样的,所以b不能叫做常量,只能叫做只读变量
        get() {
            return (Math.random() * 100).toInt()
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
    }
    
}

虽然b不能被修改,但是每次取b的值都是不一样的,所以b不能叫做常量,只能叫做只读变量

(2)定义常量的方式

object TestObject {
    const val b = 10
}

class TestObject2 {
    companion object {
        const val b = 10
    }
}

(3)kotlin中声明Long类型变量,不允许在值后用小写的L

(4)快捷键 ctrl+Q快速查看隐藏的数据类型。

3、类型转换

①Java代码中int值可以隐式转换为long,但是在Kotlin中是不允许的。

//java代码
int i = 100;
long l = i;   //隐式转换,不会报错
//kotlin代码
val i:Int = 100
val l:Long = i   //会报错

val l:Long = i.toLong()  //ok

②字符串比较
==比较值,===比较引用,这个和Java区别很大

③Raw String
"""让kotlin中的字符串保留格式输出,记得加上trimIndent()

val s = """
              第一行
      第二行
         第三行
""".trimIndent()

二、数组

1、类型区别

数组类型KotlinJava
整型IntArrayint[]
整型装箱Array< Int >Integer[]
字符CharArraychar[]
字符装箱Array< Char >Character[]
字符串Array< String >String[]

2、数组创建

val array0 = intArrayOf(0, 1, 2)
println(array0.contentToString())   //toString只能打印引用,要用contentToString
//打印结果:[0, 1, 2]

val array1 = IntArray(3) { it }
println(array1.contentToString())
//打印结果:[0, 1, 2]

val array2 = IntArray(3) { it + 1 }
println(array2.contentToString())
//打印结果:[1, 2, 3]

3、数组长度

不是length而是size

4、数组的读写

val array = arrayOf("A","B","C")
//修改
array[1]="D"
//读取
println(array[1])
//打印结果:D

5、数组的遍历

val array = arrayOf("A","B","C")
//遍历方式一:
for (e in array){
    println(e)
}

//遍历方式二:
array.forEach { e-> println(e) }
//简写
array.forEach { println(it) }

6、数组中元素判断

val array = arrayOf("A","B","C")
//判断元素是否在数组中
if("A" in array){
    println("A in array")
}

if("D" !in array){
    println("D not in array")
}

三、区间

1、创建

顺序闭区间(含首尾)

val intRange: IntRange = 1..10   //注意数据的类型
val charRange: CharRange = 'a'..'z'   //注意数据的类型
val longRange: LongRange = 1L..100L   //注意数据的类型

顺序开区间(含头不含尾)

val intRange = 1 until 10
val charRange = 'a' until 'z'
val longRange = 1L until 100L

倒序闭区间(含首尾)

val intRange = 10 downTo  1
val charRange = 'Z' downTo 'A'
val longRange = 100L downTo 1L

区间设置步长

val intRange: IntProgression = 1..10 step 2   //注意数据的类型
val charRange: CharProgression = 'a'..'z' step 3   //注意数据的类型
val longRange: LongProgression = 1L..100L step 10  //注意数据的类型

2、打印区间

val intRange = 10 downTo 1
//打印
println(intRange.joinToString())   //joinToString()

3、区间的迭代

val intRange = 1..10
//迭代一
for (element in intRange) {
    println(element)
}
//迭代二
var iterable = intRange.iterator()
while (iterable.hasNext()) {
    println(iterable.next())
}

4、区间的包含和不包含

1 in 1..10包含
1 !in 1..10不包含

四、集合框架

1、相比Java的其他特性

  • 增加了“不可变”集合框架的接口。
  • 没有另起炉灶,复用Java API的所有实现类型。
  • 提供了丰富引用的方法,例如forEach/map/flatMap
  • 运算符级别的支持,简化集合框架的访问

2、集合框架的接口类型

类型Kotlin
不可变ListList< T >
可变ListMutableList< T >
不可变MapMap<K,V>
可变MapMutableMap<K,V>
不可变SetSet< T >
可变SetMutableSet< T >

以List集合举例,不管是List<T>还是MutableList<T>编译后都是Java的List。但Kotlin中List<T>不能增减或修改元素,是不可变的。有一点要注意,Kotlin中的List和Java中的List虽然都是接口,但kotlin中的List接口在kotlin.collections包中,而Java中的List接口在java.util中,它们并不指向同一个类。

3、集合的创建

//不可变的List
val list:List<String> = listOf<String>()
//可变的List
var mutableList:MutableList<String> = mutableListOf()

//可变的map
val map:Map<String,Any> = mapOf("name" to "zhangsan","age" to 10)   //to 中缀表达式
//不可变的map
val map2:Map<String,Any> = mutableMapOf("name" to "zhangsan","age" to 10)  //to 中缀表达式

//跟java中的ArrayList不同,所在的包不一样
val stringList: ArrayList<String> = ArrayList<String>()

4、集合实现类复用与类型别名

类型别名
typealias ArrayList< E > = java.util.ArrayList< E >
typealias LinkedHashMap<K,V> = java.util.LinkedHashMap<K,V>
typealias HashMap<K,V> = java.util.HashMap<K,V>
typealias LinkedHashSet< E > = java.util.LinkedHashSet< E >
typealias HashSet< E > = java.util.HashSet< E >

通过类型别名指向了Java的uitl类,目的是为了跨平台

5、集合框架的读写

List集合

val stringList: ArrayList<String> = ArrayList<String>()
//集合添加元素方式一
stringList.add("lisi")
//集合添加元素方式二
stringList += "lisi"

//集合移除元素方式一
stringList.remove("lisi")
//集合移除元素方式二
stringList -= "lisi"

//修改元素
stringList[0]="wangwu"
//读取
var element0 = stringList[0]
var element1 = stringList.getOrNull(0)
var element2 = stringList.getOrElse(100,{
    "索引越界定义文本作为默认值"
})

//遍历
stringList.forEach {
    Log.d(TAG, "元素$it")
}

for(value in stringList){
    Log.d(TAG, "元素$value")
}

for (i in (0 until stringList.size)) {
    Log.d(TAG, "元素索引:${i},值:${stringList[i]}")
}

Map集合

val map = mutableMapOf<String, Int>("one" to 1, "two" to 2)
//取键和值
map.get("one")   //1
map["one"]   //1
map.getOrDefault("three", 0)  //0
map["four"]   //null

//过滤
map.filter { (key, value) -> value > 1 }
//按键过滤
map.filterKeys { key -> key.startsWith("o") }
//按值过滤
map.filterValues { value -> value > 0 }

//加减操作符
val map1 = map + Pair("three", 3)
val map2 = map + Pair("one", 3)
val map3 = map + mapOf<String, Int>("three" to 3)

val map4 = map - "one"
val map5 = map - listOf<String>("one", "three")  //注意这里是listOf

//添加与更新操作
map.put("three", 3)
map["three"] = 3
map.putAll(mapOf("four" to 4))
map += mapOf("four" to 4)

//删除操作
map.remove("one")
map.keys.remove("one")
map.values.remove(1)
map -= "one"

//遍历
map1.forEach {
    Log.d(TAG, "键:${it.key},值:${it.value}")
}

for ((key,value) in map1){
    Log.d(TAG, "键:${key},值:${value}")
}

Pair

val pair: Pair<String, Int> = "one" to 1
val pair1: Pair<String, Int> = Pair("one",1)
val first  = pair.first    //获取前面的元素
val second  = pair.second    //获取第二个元素
val (x, y) = pair   //解构写法

Triple

val triple: Triple<String, Int, Int> = Triple("one", 1, 1)
val first = triple.first
val second = triple.second
val third = triple.second
val (x, y, z) = triple   //解构写法

五、函数基本概念

  • 有自己的类型,所以是“一等公民”
  • 可以赋值、传递,并在合适的条件下调用

1、函数的引用

假如有二个类

class Foo {
    fun bar() {

    }
}

class Uoo {
    fun uMethodOne(block: () -> Any) {

    }
}

函数的引用

//对比Foo::bar和foo::bar的区别
var foo = Foo()
var x = foo::bar
var x1: () -> Any = x   //x和x1是等价的,只是拆开看更清楚

var z = Foo::bar
var z1: (Foo) -> Any = z   //z和z1是等价的,调用z1需要传入Foo对象

//使用函数的引用
var uoo = Uoo()
uoo.uMethodOne { foo.bar() }
uoo.uMethodOne { foo::bar }
uoo.uMethodOne { x }
uoo.uMethodOne { z }

2、变长参数

//传入string的集合
fun main(args: Array<String>) {
    println(args.contentToString())
}

//可变参数
//注意:与上面的方法互斥,因为它们是等价的,编译成java的代码完全相同
fun main(vararg args: String) {
    println(args.contentToString())
}

//取参数也就和集合的取值一样
args[0]

3、多返回值

//多返回值
fun main(): Pair<String, String> {
    return Pair("A", "B")
}

fun main2(): Triple<String, String, String> {
    return Triple("A", "B", "C")
}

调用

var pair: Pair<String, String> = main()
var (value0, value1) = main()   //解构写法

var triple: Triple<String, String, String> = main2()
var (value2, value3, value4) = main2()   //解构写法

4、默认参数

//默认参数
fun foo(name: String, age: Int = 0) {

}

调用

foo("A")

注意:为了避免传参和阅读代码时错乱,默认参数应该放在传参的最后,不要放在前面和中间。

5、具名参数

通俗的解释就是给参数起名字

//具名参数
fun foo(name: String, address:String) {

}

调用

foo(name="张三",address="北京市")

告诉编译器哪个对应哪个。

--个人学习笔记