Kotlin基础入门之必知必会,查漏补缺来一手~~~
数据类型
Kotlin跟 java 相同,基本数据类型有八种 boolean,char,int,short,long,float,double,byte
类型 | 位宽 | 最小值 | 最大值 |
---|---|---|---|
Short | 16 | -32768 | 32767 |
Int | 32 | (-2^31) | (2^31-1) |
Long | 64 | (-2^63) | (2^63-1) |
Byte | 8 | -128 | 127 |
Float | 32 | - | - |
Double | 64 | - | - |
根据数据类型,结合代码看下
// 如果变量是数字,kotlin 的数据类型默认就是 Int 类型,如果超出了 Int 的取值范围,编译器就会自动推断为 Long 类型 // 根据 number 的取值范围,推断出 number 为 Int 类型 val number = 100 // 显示声明为 Int 类型 val intNumber: Int = 100 // 由于 number2 的取值范围超出 Int 的范围,编译器推断该变量升级成 long 类型 val number2 = 9999999999 // 显示声明为 long 类型 val longNumber: Long = 100L // Kotlin 对小数的默认推断是 Double 类型(如同Java) val number3 = 3.1415926535898 // 显示声明为 Double 类型 val doubleNumber: Double = 3.1415926535898 // 如需要声明 Float 类型,则只需在变量后面添加 F/f 即可 val number4 = 3.1415926535898f // 显示声明为 Float 类型 // val floatNumber:Float = 3.1415926535898 // 这边编译会报错,原因如下 // 特别留意的是,kotlin 的 Float 类型十进制位数规定了6位,所以如果超出了6位,则会出现精度丢失的情况 println("number4: $number4") // 输出结果为:number4: 3.1415927 // 多说一句,Kotlin 与 Java 有一点不同的是,Kotlin 是不会像 Java 进行变量的隐形转换的,举个栗子, // 你如果声明了 Double 变量,就只能接受 Double 类型的值,不能接收 Float 、 Int或者其他基本类型。 // 字符串类型(引用类型) val str = "hello world" // 显示声明为 String 类型 val strString: String = "hello world" // 可通过下标值来取 val str1 = str[4] // 这里取出的值是 o ,并且是 char 类型 // 关于 Kotlin 的输出方式可以通过模板模式来输出,如下 println("str is $str1") // str is o println("str length is ${str.length}") // str length is 11 // 其他类型就不一一演示了,跟上面演示的都差不多了。
Kotlin 是通过调用 to+基本类型来实现类型之间的强制转换
类型 | 强转方法 |
---|---|
Byte | toByte() |
Char | toChar() |
Short | toShort() |
Int | toInt() |
Long | toLong() |
Float | toFloat() |
Double | toDouble() |
Boolean | - |
扩展: 由于不同的表示方式,较小类型并不是较大类型的子类型,较小的类型不能隐式转换为较大的类型。 这意味着在不进行显式转换的情况下我们不能把 Byte 型值赋给一个 Int 变量。(菜鸟教程)例如:val b: Byte = 1 // OK,字面值是静态检测的 val i; Int = b // 错误 val i: Int = b.toInt() // OK
数组
数组是一种初始化时指定容器大小,不可以动态调整其大小的容器。kotlin为数组增加了一个Array类,为元素是基本类型的数组增加了IntArray、Double类等其他基本类型。
下面介绍Kotlin常用的数据创建方式
// 1.使用arrayOf创建数组,必须指定数组的元素,数组中的元素可以是任意类型 val arrayNumber = arrayOf(1, 2, 3, 4, 5) // 显示声明 Int 类型 val arrayNumber2: Array<Int> = arrayOf(1, 2, 3, 4, 5) // 可通过下标值来赋值 arrayNumber[4] = 6 // 不显示声明类型时,可以是任意类型 val arrayNumber3 = arrayOf(1, 2, "3", true, JSONObject()) // 也可以声明为 Any 类型,相当于 Java 的 Object val arrayNumber4: Array<Any> = arrayOf(1, 2, "3", true, JSONObject()) // 2.使用arrayOfNulls创建一个指定大小且所有元素为空的数组,必须指定集合中的元素类型以及长度 val list = arrayOfNulls<String>(5) list[0] = "zhangsan" ... // 3.利用array的构造函数,动态创建数组 // 用接受数组大小以及一个方法参数的 Array 构造方法,用作参数的方法能够返回给定索引的每个元素初始值 val array = Array(10) { it -> (it * it).toString() } // 普通的foreach方法,将数组里面的数据进行输出 array.forEach { it -> println(it) } // foreach增强版,会依次回调给我们数组中的索引和元素值 array.forEachIndexed { index, item -> println("$index : $item") }
当然,Kotlin中同样也会提供专门的原生类型数组:
原生类型数组 | 解释 |
---|---|
ByteArray | 字节型数组 |
ShortArray | 短整型数组 |
IntArray | 整型数组 |
LongArray | 长整型数组 |
BooleanArray | 布尔型数组 |
CharArray | 字符型数组 |
FloatArray | 浮点型数组 |
DoubleArray | 双精度浮点型数组 |
由于原生数组跟普通的数组定义一样,具体怎么使用,就不一一展示了
扩展: 因为在Kotlin数组类型不属于集合的一种,虽然用法跟集合很相似,数组和集合之间可以互相转换,初始化集合的时候可以传入数组
集合
集合在Kotlin中应用非常广泛,例如普通的变量集,对象集,封装json类型的请求参数集合等等。集合与数组最明显的特点就是集合可以动态改变自己的长度,数组不可以。
List:有序集合,可以通过索引下标来访问元素。允许数据重复
Set:无序且唯一的集合,set中的元素顺序不会按照插入的顺序一样,并且不允许出现重复元素
Map:也称字典,是一种以键值对存在的集合,键是唯一的,每个键对应着特定的值,且值允许重复
创建方式 | 范例 | 说明 | 是否可变 |
---|---|---|---|
arrayListOf() mutableListOf () | arrayListOf(1,2,3) mutableListOf() | 必须指定元素类型 | 是 |
listOf() | listOf(1,2,3) | 必须指定元素类型和初始化数据元素 | 否 |
arraySetOf() mutableSetOf () | arraySetOf(1,2,3)) mutableSetOf() | 集合内元素会自动去重 | 是 |
setOf() | setOf(1,2,3) | 必须指定元素类型,自动去重 | 否 |
arrayMapOf< K,V >() mutableListOf < K,V >() | arrayMapOf(Pair("key","value")) mutableMapOf() | 初始元素使用Pair包装 | 是 |
mapOf() | mapOf(Pair("key","value")) | 必须指定初始元素,使用Pair包装 | 否 |
mutableListOf
的常用Api如下
example.reverse() // 集合反转(倒序输出)
example.shuffle() // 随机排列元素(随机输出)
example.sort() // 顺序输出(按a-z的顺序) sortDescending 则相反
方法
下面将Kotlin的方法分为下面三个模块进行讲解
方法声明
方法参数
方法用法
方法声明
Kotlin有三种声明方法的方式,分别为
普通类的方法
静态类的方法
companion object 伴生类的方法
普通类的方法
class Person { fun test() { println("成员方法") } }fun main() { // 普通类的成员方法声明与调用 // 需要先构建实例对象,才能访问成员方法 Person().test() }
静态类的方法
如果想要实现一个工具类的话,可以通过关键字object
来创建一个静态类
object commonUtil { fun add(x: Int, y: Int): Int { return x + 2 } }fun main() { // 静态类里面的方法,都是属于静态方法 // 不需要构建实例对象,可以通过类名来访问静态方法 commonUtil.add() }
companion object伴生类的方法
虽然Kotlin中没有static关键字,但是我们可以通过companion object
来实现类静态方法的目的
class Person { fun test() { println("成员方法") } companion object{ fun test2() { println("静态方法") } } }fun main() { // 普通类的成员方法声明与调用 // 需要先构建实例对象,才能访问成员方法 Person().test() // 可通过类名来调用方法 Person.test() }
方法参数
默认参数
具名参数
可变数量的参数
默认参数
方法中的参数可以有默认值,可以通过类型后面的=
来设置默认值
fun add(x: Int = 0, y: Int) {}
具名参数
如果一个默认参数在一个无默认值的参数之前,那么无默认值的参数,只能通过使用具名参数
来调用该方法来使用
fun add(x: Int = 0, y: Int) {} add( y = 1) // 仅通过给 y 赋值,而 x 使用默认值 0
如果最后一个参数是方法,那么它既可以作为具名参数
在括号内传入,也可以在括号外传入
fun add(x: Int = 0, y: Int, action:() -> Unit) {} read(y = 1){println("hello")} // 括号外传入read(y = 1, action = {println("hello")}) // 括号内传入
可变数量的参数
方法的参数(通常是最后一个)可以用vararg
修饰符标记
fun append(vararg str: Char): String { val result = StringBuffer() for (char in str){ result.append(char) } return result.toString() }
传递可变数量的参数
append('k','o','t','l','i','n')
if表达式
带返回值 if 表达式
在kotlin当中,由于if是一个表达式所以它会返回一个值,表达式的值为表达式作用域内最后一行的值。
fun max(a: Int, b: Int): Int { return if ( a > b ) a else b }
多级 if 表达式
fun eval(number: Number) { if (number is Int) { println("this is int number") } else if (number is Double) { println("this is double number") }else if (number is Long) { println("this is long number") } ... }fun main() { eval(100) }
when表达式
fun eval(number: Number): String = when (number) { is Int -> this is int number is Double -> this is double number is Long -> this is long number ... }fun main() { eval(100) }
循环控制
for循环
for循环可以对任何提供迭代器iterator
的对象进行遍历,写法为 for item
in elements
,最常用的应用就是迭代集合
val items = listOf("kotlin","java","python")for (item in items) {println(item)}
除此之外,扩展一下,for循环还有两种其他遍历方式
val items = listOf("kotlin","java","python") items.forEach {item -> println("forEach:${item}")} items.forEachIndexed {index, item -> println("forEachIndexed:${index},${item}")}
do-while
// 当 condition 为 true时执行循环体while(condition) { ... }// 循环体第一次会无条件地执行。之后,当condition为true时才执行do { ... } while (condition)
迭代区间和数列
for 可以循环遍历任何提供了迭代器的对象。即:有一个成员函数或者扩展函数 iterator()
,它的返回类型,有一个成员函数或者扩展函数 next()
,并且有一个成员函数或者扩展函数 hasNext()
返回Boolean
for (i in 1..10) { // 遍历区间,kotlin的区间的包含 [1,10] print("$i ") // 输出结果为 : 1 2 3 4 5 6 7 8 9 10}for (i in 1 until 10) { // until 不包含最后一个元素,左闭右开的区间 [1,10) print("$i ") // 输出结果为 : 1 2 3 4 5 6 7 8 9}for (i in 10 downTo 1 step 2) { // 从 10 开始,每隔2个元素打印一次 print("$i ") // 输出结果为 : 10 8 6 4 2}
break 和 continue
break:终止最外层的循环
continue:终止当前循环,开始下一次循环
泛型
泛型是一种语法糖,其实就是把类型参数化,它的引入给强类型编程语言加入了更强的灵活性。
好处
将代码通用化,可应用到多个业务模块
增强代码的健壮性,避免了
ClassCastException
类转换异常方便造轮子,解决实际的问题
常见的泛型应用有:泛型类、泛型接口、泛型方法和泛型属性
泛型接口/泛型类(泛型类型)
定义泛型类型,是在类型名之后、主构造函数之前用尖括号括起的大写字母类型参数指定:
泛型接口
interface Person<T> { fun study(): T fun run(t: T)}class Student : Person<String> { override fun run(t:String) { print("run:${t}") } }fun main() { val student = Student() student.run("跑步") }
泛型类
abstract class Color<T>(val t: T) { abstract fun printColor()}class BlueColor(val color: String) : Color<String>(color) { override fun printColor() { print("printColor:${color}") } }fun main() { val blueColor = BlueColor("蓝色") }
泛型字段
定义泛型类型字段,可以完整地写明类型参数,如果编译器可以自动推定类型参数,也可以省略类型参数
abstract class Color<T>(val t: T /*泛型字段*/) { abstract fun printColor()}
泛型方法
fun <T> fromJson(json: String, tClass: Class<T>): T? { val t: T? = tClass.newInstance() return r }fun main() { fromJson("{}", String::class.java) }
至此,Kotlin的入门教程就告一段落了,后续要需要补充的再更新,感谢观看 ✿✿ヽ(°▽°)ノ✿
来源https://www.cnblogs.com/hyxiao97/p/15364559.html