一、基本类型
1、类型
| 类型 | Kotlin定义 | Java定义(含包装类型) |
|---|---|---|
| 字节 | Byte | byte/Byte |
| 整型 | Int&Long | int/Integer&long/Long |
| 浮点型 | Float&Double | float/Float&double/Double |
| 字符 | Char | char/Character |
| 字符串 | String | String |
Kotlin的类型还分为有符号类型和无符号类型
| 数据类型 | 有符号类型 | 无符号类型 |
|---|---|---|
| 字节 | Byte | UByte |
| 短整型 | Short | UShort |
| 整型 | Int | UInt |
| 长整型 | Long | ULong |
| 字符串 | String | String |
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、类型区别
| 数组类型 | Kotlin | Java |
|---|---|---|
| 整型 | IntArray | int[] |
| 整型装箱 | Array< Int > | Integer[] |
| 字符 | CharArray | char[] |
| 字符装箱 | 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 |
|---|---|
| 不可变List | List< T > |
| 可变List | MutableList< T > |
| 不可变Map | Map<K,V> |
| 可变Map | MutableMap<K,V> |
| 不可变Set | Set< T > |
| 可变Set | MutableSet< 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="北京市")
告诉编译器哪个对应哪个。