系列文章路引 👀
文章目录
- 系列文章路引 👀
- 一、基本类型
- 1.数值类型
- 2.布尔类型
- 3.字符型
- 4.字符串类型
- 5.val与var的区别
- 二、数组
- 1.java与kotlin常规使用对比
- 2.kotlin size() 与 java length()
- 3.数组的常用方式
- 三、区间(kotlin 特有的概念,java没有)
- 1.开区间 ..
- 2.左闭右开 util
- 3.倒叙区间 downTo
- 4.区间步长 step
- 5.区间的迭代
- 6.注意点
- 三、集合框架
- 1.kotlin集合框架与java对比
- 2.使用方式
- 3.补充Pair 键值对 与 Triple 三个元素
- 四、函数
- 1.介绍
- 2.函数的类型,引用
- 3.变长参数 vararg
- 4.多返回值(上面提到的Pair 以及 Triple )
- 5.默认参数
- 6.函数传递调用
- 五、总结
一、基本类型
- Java:区分基本数据类型以及引用类型, 基本数据类型有byte、short、int、long、float、double、char、boolean,八大基本数据类型。而Kotlin 中没有基础数据类型,只有封装的数字类型,你每定义的一个变量,其实 Kotlin 帮你封装了一个对象,这样可以保证不会出现空指针。
- Kotlin:基本数值类型(继承了Number)有Byte、Short、Int、Long、Float、Double。Char与Boolean不属于数值类型。
如下:Java与Kotlin类型对比
Kotlin | java | |
字节 | byte/Byte | Byte |
整形 | Int & Long | int/Integer & long/Long |
浮点型 | Float & Double | float/Float & double/Double |
字符 | Char | char/Character |
字符串 | String | String |
1.数值类型
- Kotlin 的基本数值类型包括 Byte、Short、Int、Long、Float、Double 等和java类似只不过第一个字符是大写。不同于 Java 的是,字符不属于数值类型,是一个独立的数据类型。
- 装箱和拆箱,kotlin的原则是万物皆对象,所以并没有和java中一样的 int 和 Integer 这种数据类型和引用类型的分别,因此kotlin中只存在数字的装箱,并没有拆箱
类 型 | 类 型 | 宽 度 |
Double | 双精度浮点型 | 64 |
Float | 浮点型 | 32 |
Long | 长整型 | 64 |
Int | 整形 | 32 |
Short | 短整型 | 16 |
Byte | 字节 | 8 |
var a: Double = 2.0
//F表示单精度浮点型
var b: Float = 2F
//L表示长整型
var c: Long = 1L
var d: Int = 1
var e: Short = 1
var f: Byte = 5
如下:可省略编译类型
//kotlin 默认可识别为Long类型
var c= 124L
kotlin允许存在隐式转换,必须调用对应的方法进行显示转换!!! 如下
var e = 3.0
var f = e.toLong()
var float1 = 1f
var double1 = float1.toDouble()
kotlin支持无符号类型(表示的范围是 有符号类型去除负数的部分,正数部分乘以2倍)
使用:在正常类型前加U 如下
val g:UInt = 9778u
val h:UByte = 1u
val i:UShort = 107u
val j:ULong = 102435u
println("Range of Int:[${Int.MAX_VALUE},${Int.MIN_VALUE}]")
println("Range of UInt[${UInt.MAX_VALUE},${UInt.MIN_VALUE}]")
//运行结果如下
Range of Int:[2147483647,-2147483648]
Range of UInt[4294967295,0]
2.布尔类型
- Boolean 表示布尔类型,和Java相同有true和false两个值
var value: Boolean = false
var a: Boolean = false
var b: Boolean = true
var result = Boolean
//输出结果为 value==false
println("value==$value")
//输出结果为 a && b
if (a || !b) {
println("a==b")
}
if (!a && b) {
print("a && b")
}
3.字符型
- Char:字符型,单引号(’ ')表示字符变量,需要显式转换为数字不饿能直接作为数字
var a: Char = 'a'
println(a)
var var1 = a.toByte()
var var2 = a.toInt()
var var3 = a.toString()
var var4 = a.toFloat()
var var5 = a.toShort()
println("var1 = $var1 ,var2 = $var2 , var3 = $var3 , var4 = $var4 , var5 = $var5")
//输出结果为 var1 = 97 ,var2 = 97 , var3 = a , var4 = 97.0 , var5 = 97 97为a的ASCII码值
大小写转换,如下:
var a: Char = 'a'
// 转换为大写
a = a.toUpperCase()
println("$a----------") //输出结果为 A----------
// 转换为小写
a = a.toLowerCase()
println("$a++++++++++") //输出结果为 a++++++++++
4.字符串类型
字符串用法和java一致,这里引入两个kotlin特有的东西
- 1.kotlin字符串比较。java比较引用使用"==",比较值类型使用"equals()"。而kotlin比较引用使用"===",比较值类型使用"=="。如下:
val l = "Today is sunny day"
val m = String("Today is sunny day".toCharArray())
//kotlin 比较
// compare values true
println(l==m)
// compare references false
println(l===m)
//java 比较
// compare values true
println(l.equals(m))
// compare references false
println(l==m)
- 2.kotlin特有的字符串模板 “”" “”" 可以保持格式。如下:
//函数 trimIndent() 去除空格
val s = """
hello
world
nice to meet you
welcome to china
""".trimIndent()
//输出结果
//hello
// world
// nice to meet you
//welcome to china
5.val与var的区别
val:表示只读变量,即赋值之后不可更改。
var:表示可读写变量,赋值之后可更改
解析为java代码后,var修饰与val修饰并没有区别,但是在kotlin里面,val代表只读变量又称作运行时常量
// 可读写变量
var a: Int = 1
// 只读变量
val b: String = "hello world"
// 反编译为java代码
int a = true;
String b = "hello world";
既然在kotlin里面val修饰都已经不可变了,为什么还称作只读变量(运行时常量呢),不叫常量呢?
我们所熟知的java常量指的是编译时常量,即编译期间才会确定的常量。而运行时常量是指在代码运行时才会确定的常量,不同的运行方式可能获取不同的值,所以叫只读变量(运行时常量)。如下代码所示
//如下 cc具体会返回什么样的值 需要在运行期间 走具体的分支才知道
var bb = true
val cc : Int = if (bb){
1
}else{
2
}
那kotlin具体的常量如何表示呢?使用const关键字,具体内容在后面的章节会讲的到。
二、数组
1.java与kotlin常规使用对比
kotlin | java | |
整形 | IntArray | int[] |
整形装箱 | Array<Int> | Integer[] |
字符 | CharArray | char[] |
字符装箱 | Array<Char> | Character[] |
字符串 | Array<String> | String[] |
代码如下(示例):
//创建一个Int数组
val arr1 = intArrayOf(1, 2, 3, 4, 5) //type IntArray 整形
val arr2 = arrayOf(1, 2, 3, 4, 5) //type Array<Int> 装箱类型
val arr3 = IntArray(5) { it + 1 }
val arr7: Array<String> = arrayOf("array", "string")
// 创建二维数组 数组需要初始化 int默认为0 String手动初始化为""
val square = Array(10000) { IntArray(10000) }
val square1 = Array(10000) { Array<String>(10000) { "" } }
//tostring 打印对象信息 contentToString kotlin特有的方法 打印
println(arr1.toString())
println(arr1.contentToString())
println(arr2.contentToString())
println(arr3.contentToString())
println(arr7.contentToString())
//结果输出
[I@15db9742
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[array, string]
2.kotlin size() 与 java length()
我们都知道java里面数据获取长度使用length属性,集合使用size()方法。在kotlin里面统一使用size
// 长度 kotlin size java length
//kotlin
println(arr1.size)
//java
println(arr1.length)
3.数组的常用方式
for循环以及foreatch
//数组的遍历
val arr6 = floatArrayOf(1.0f, 2.0f, 3f, 5f)
for (element in arr6) {
println(element)
}
arr6.forEach { element ->
println(element)
}
arr6.forEach { it ->
println(it)
}
arr6.forEach {
println(it)
}
//判断是否存在值
val empty = arr6.isEmpty()
println(empty)
//判断是否至少存在一个元素 其实内部就是调用了!isEmpty()
val any = arr6.any()
println("any is $any")
//判断一个值存在一个数据
if (arr6.any { it == 1.0f }){
println("1.0f exists in variable 'arr6'")
}
if (!arr6.any { it == 1.2f }){
println("1.2f not exists in variable 'arr6'")
}
三、区间(kotlin 特有的概念,java没有)
1.开区间 …
val intRange=1..10 //[1,10]
val charRange='a'..'z'
val longRange=1L..100L
2.左闭右开 util
val intRangeExclusive=1 until 10 //[1,10)
val charRangeExclusive='a' until 'z'
val longRangeExclusive=1L until 100L
3.倒叙区间 downTo
val intRangeReverse=10 downTo 1 //[10,9,8,...,1]
val charRangeReverse='z' downTo 'a'
val longRangeReverse=100L downTo 1L
4.区间步长 step
val intRangeStep=1 .. 10 step 2 //[1, 3, 5, 7, 9]
val charRangeStep='a' .. 'z' step 2
val longRangeStep=1L ..100L step 5
5.区间的迭代
val intRange = 1..10
for (element in intRange){
println(element)
}
intRange.forEach { it->
println(it)
}
//类似java for循环
val arrayOf = arrayOf(1, 2, 3, 4, 5)
for (i in 0 until arrayOf.size) {
println(i)
}
//和上一种写法相等
for (i in arrayOf.indices) {
println(i)
}
6.注意点
小数的区间是不可数的,所以不能够被打印。但是可以进行包含关系判断
// 小数 区间 是不可数的 不可以进行打印
val floatRange = 1f..2f
val doubleRange = 1.0..2.0
println(floatRange.toString())
if (1.2f in floatRange){
println(true)
}
// 结果
1f..2f
true
三、集合框架
1.kotlin集合框架与java对比
- 增加了“不可变”集合框架接口
- 没有另起炉灶,服用java api的所有实现类
- 提供丰富易用的方法,列如 forEach/map/flatMap
- 运算级别的支持,简化api的访问
kotlin | java | |
不可变List | List<T> | List<T> |
可变List | Mutable<T> | List<T> |
不可变Map | Map<K,V> | Map<K,V> |
可变Map | Mutable<K,V> | Map<K,V> |
不可变Set | Set<T> | Set<T> |
可变Set | MutableSet<T> | Set<T> |
kotlin集合框架服用javaAPI,只是使用typealias使用kotlin的包名,具体源码如下
@SinceKotlin("1.1") public actual typealias ArrayList<E> = java.util.ArrayList<E>
@SinceKotlin("1.1") public actual typealias LinkedHashMap<K, V> = java.util.LinkedHashMap<K, V>
@SinceKotlin("1.1") public actual typealias HashMap<K, V> = java.util.HashMap<K, V>
@SinceKotlin("1.1") public actual typealias LinkedHashSet<E> = java.util.LinkedHashSet<E>
@SinceKotlin("1.1") public actual typealias HashSet<E> = java.util.HashSet<E>
2.使用方式
除了java的常规使用方式,kotlin可直接使用listOf或者mutableListOf等创建,listOf创建的是Kotlin的List接口不可变的,不可以进行增删,mutableListOf返回对应的ArrayList,是可变的
MutableMapOf源码 默认返回了LinkedHashMap 该类继承HashMap是基于HashMap和双向链表来实现的。 线程不安全 但是可以保证插入时的顺序 且效率和HashMap没有区别 所以kotlin默认返回了LinkedHashMap
// 不可修改 不能添加或者删除元素
val intList: List<Int> = listOf(1, 2, 3, 4, 5, 6, 7)
// 可以修改
val mutableList: MutableList<Int> = mutableListOf(1, 2, 3, 4, 5, 6, 7, 8)
// map
val map = mapOf<String, Any>("name" to "zxf", "age" to 18)
val map2 = mutableMapOf<String, Any>("name" to "liSi", "age" to 22)
// java get操作
val name = map["name"]
// java set操作
map2["name"] = "王五"
// MutableList源码 默认返回了ArrayList
public fun <T> mutableListOf(vararg elements: T): MutableList<T> =
if (elements.size == 0) ArrayList() else ArrayList(ArrayAsCollection(elements, isVarargs = true))
// MutableMapOf源码 默认返回了LinkedHashMap 该类继承HashMap是基于HashMap和双向链表来实现的。 线程不安全 但是可以保证插入时的顺序 且效率和HashMap没有区别 所以kotlin默认返回了LinkedHashMap
public fun <T> mutableListOf(vararg elements: T): MutableList<T> =
if (elements.size == 0) ArrayList() else ArrayList(ArrayAsCollection(elements, isVarargs = true))
// mutableMapOf测试使用
val map2 = mutableMapOf<String, Any>("name" to "liSi", "age" to 22)
map2.put("sex","boy")
map2.put("height",172)
// 修改name值
map2["name"] = "zzz"
map2.forEach{
println("key:${it.key}-----value:${it.value}")
}
// 结果输出 顺序不变
key:name-----value:zzz
key:age-----value:22
key:sex-----value:boy
key:height-----value:172
也可以直接生成集合对象使用
val stringList = ArrayList<String>()
// add
for (i in 0..10) {
stringList.add("num:$i")
}
for (i in 0..10) {
stringList += "num:$i"
}
// remove
for (i in 0..10) {
stringList.remove("num:$i")
}
for (i in 0..10) {
stringList -= "num:$i"
}
3.补充Pair 键值对 与 Triple 三个元素
Pair 键值对对象
Triple 三个元素
可通过属性拿到值,也可以通过解构获取结果。
解构具体在后面的章节会讲到,具体先看用法
// Pair 键值对
val pair = "name" to "zxf"
val pair1 = Pair("name", "zxf")
// 获取pair 对应的元素
val first = pair.first
val second = pair.second
// 解构
val (x, y) = pair
println("x:$x----y:$y")
// Triple 三个元素
val triple = Triple<String, Int, Int>("zxf", 1, 1)
val first1 = triple.first
val second1 = triple.second
val third = triple.third
val (g, t, z) = triple
println("g:$g----t:$t----z:$z")
// 输出
x:name----y:zxf
g:zxf----t:1----z:1
四、函数
1.介绍
- kotlin函数有自己的类型,被誉为“一等公民”
- 可以赋值、传递、并在合适的条件下使用(Unit 相当于 java里面的void)
- java里面的方法可以理解为函数的一种类型,自带receiver。(方法可以理解为放在类里面的函数,receiver则指的是对应类的实例化)。
2.函数的类型,引用
函数是有类型的,比如
fun foo(){} 的类型就是 ()-> Unit,代表无参无返回值
fun foo(p0:Int):String{…} 的类型是 (Int)->String, 需要int类型的参数,返回String类型
class Foo{ fun foo(p0:Int):String{…} } 的类型是Foo.(Int)->String , 代表receiver是Foo,需要int参数,返回String类型。类型也可以表示为(Foo,Int)->String 和 Function3(Foo,Int,String)
函数的引用 receiver::functionname,如下所示
class Foo {
fun bar(p: String, p0: Int) {
println("$p,$p0")
}
}
// 可变参数
fun main(vararg args: String) {
println(args.contentToString())
// 函数引用传递
val x = Foo::bar
val w: Foo.(String, Int) -> Unit = Foo::bar
val y: (Foo, String, Int) -> Unit = x
val z: Function3<Foo, String, Int, Unit> = x
// Foo.(String, Int) -> Unit = (Foo, String, Int) -> Unit = Function3<Foo, String, Int, Unit>
}
3.变长参数 vararg
fun varargParameter(vararg p: String) {
println("可变长参数:${p.joinToString(":")}")
}
//调用
varargParameter("a","b","c","d","e","f")
4.多返回值(上面提到的Pair 以及 Triple )
利用解构接收,简化代码
// 多返回值
fun multiReturnValues(): Triple<String, Int, Int> {
return Triple("zxf", 1, 1)
}
// 利用 Triple 或者 pair 可实现伪多返回值
val (q, h, e) = multiReturnValues()
println("q:$q,h:$h,e:$e")
5.默认参数
// 默认参数
fun defaultParameter(p: Int = 0, p0: String, p1: Float = 1f): Int {
return p
}
// 默认参数 如果传入的参数 不是默认第一个 可指定参数名字传递
val defaultParameter = defaultParameter(p0 = "hello")
println(defaultParameter)
6.函数传递调用
看如下例子,首先利用函数的类型声明函数,在引用对应的函数,当作参数传递
// 需要一个receiver为Foo,参数为String、Int 返回类型为Unit的函数
fun yy(p: (Foo, String, Int) -> Unit) {
//调用p 第一个参数为 对应的recevier
p(Foo(), "hello", 1)
}
// receiver 为Foo 参数为String、Int 无返回类型
class Foo {
fun bar(p: String, p0: Int) {
println("$p,$p0")
}
}
// 引用 传参 调用yy函数
fun main(vararg args: String) {
val foo : Foo.( String , Int ) -> Unit = Foo::bar
//上下等价
//val foo : (Foo , String , Int ) -> Unit = Foo::bar
yy(foo)
}
// 输出结果
hello,1
五、总结
以上学习完毕后,可实现简单的demo,将知识融会贯通,如下 简单的四则运算 看看和java实现有如何的区别。
fun main(vararg args: String) {
computer("1", "+", "1")
}
fun computer(vararg args: String) {
if (args.size < 3) {
return showHelp()
}
val map = mapOf(
"+" to ::add,
"-" to ::reduce,
"*" to ::multiply,
"/" to ::eliminate
)
// 如果为null 则返回
val kFunction2 = map[args[1]] ?: return showHelp()
try {
println("Input:${args.joinToString(" ")}")
println("Output:${kFunction2(args[0].toInt(), args[2].toInt())}")
} catch (e: Exception) {
println("Invalid Arguments")
showHelp()
}
}
fun add(p: Int, p1: Int): Int {
return p + p1
}
fun reduce(p: Int, p1: Int): Int {
return p - p1
}
fun multiply(p: Int, p1: Int): Int {
return p * p1
}
fun eliminate(p: Int, p1: Int): Int {
return p / p1
}
fun showHelp() {
val content = """
Simple Template
Input:3 * 5
Output:15
""".trimIndent()
println(content)
}