一基本数据类型
Kotlin的基本数据类型跟java高级语言一样,包括整型,长整型,浮点型,双精度,布尔型,字符型,字符串这几种常见类型。
1.1Kotlin和Java的基本数据类型的对比
基本数据类型名称 | Kotlin的数据类型 | Java的数据类型 |
---|---|---|
整型 | Int | int 和 Integer |
长整型 | Long | long和Long |
浮点型 | Float | float和Float |
双精度 | Double | double和Double |
布尔型 | Boolean | boolean和Boolean |
字符型 | Char | char |
字符串 | String | String |
1.2变量的声明
格式:var 变量名:变量类型
例如: var i:Int =0;至于后面的分号,则看代码行后面是否还有其他语句,如果变量声明完毕直接回车换行,那么后面无需带分号;如果没有回车换行,而是添加其他语句,那么变量声明语句要带上分号
1.3变量之间的转换
Kotlin变量的另一个重要特点是类型转换,在Java开发中,如int、 long、 float、 double类型的变量可以直接在变量名前面加上诸如(int) 、(long) 、(float)、(double) 这种表达式进行强制类型转换;对于int (整型)和char (字符型)这两种类型,甚至都无须类型,只能调用类型转换函数输出其他类型的变量,表2-2是常见的几种类型转换函数的说明。.
Kotlin的数据类型转换函数 | 转换函数说明 |
---|---|
toInt | 转换为整型数 |
toLong | 转换为长整型 |
toFloat | 转换为浮点数 |
toDouble | 转换为双精度数 |
toChar | 转换为字符 |
toString | 转换为字符串 |
val origin: Float = 65f;
tv_string.text = origin.toString()
var int: Int;
int = origin.toInt();
tv_integer.text = int.toString();
var long: Long;
long = origin.toLong()
tv_long.text = long.toString()
var double: Double
double = origin.toDouble();
tv_double.text = double.toString()
var boolean: Boolean
boolean = origin.isNaN()
tv_boolean.text = boolean.toString()
var char: Char
char = origin.toChar()
tv_char.text = char.toString()
注意到上述类型转换代码的第一行变量声明语句以val开头,而其余的变量声明语句均以var开头,这是为什么呢?其实val和var的区别在于,前者修饰过的变量只能在第一次声明时赋值,后续不能再赋值;而后者修饰过的变量在任何时候都允许赋值。方便记忆的话,可以把val看作是Java里的final关键字;至于var, Java里面没有对应的关键字,就当它是例行公事好了。
二:数组
2.1数组变量的声明
java中声明一个整型数组如下:
int[] int_array=new int[]{1,2,3,4};
其他的类型只要把int替换成long,float,double,boolean,char,其中之一即可。
但是在Kotlin中,声明并初始化一个整型数组是下面这样的:
var int_array:IntArray= intArrayOf(1,2,3,4)
Kotlin与Java之间的区别:
- Kotlin另外提供了新的整型数组类型,即IntArray
- 分配一个常量数组,Kotlin调用的是intArrayOf方法,并不使用new关键字
其他的基本数组类型:
Kotlin的基本数组类型 | 数组类型的名称 | 数组类型的初始化方法 |
---|---|---|
整型数组 | IntArray | intArrayOf |
长整型数组 | LongArray | longArrayOf |
浮点型数组 | FloatArray | floatArrayOf |
双精度数组 | DoubleArray | doubleArrayOf |
布尔类型数组 | BooleanArray | booleanArrayOf |
字符数组 | CharArray | charArrayOf |
不知读者有没有注意到,上面的Kotlin数组类型不包括字符串数组,而Java是允许使用字符串数组的,声明字符串数组的Java代码示例如下:
String[] string_array=new String[]{"how","are","you"}但在Kotlin这里,并不存在名为StringArray的数组类型,因为String是一种特殊的基 本数据类型。要想在Kotlin中声明字符串数组,得使用Array<String>类型,也就是把“String"”用尖括号包起来。同时,分配字符串数组的方法也相应变成了arrayOf,下面是声明字符串数组的Kotlin代码:这种字符串数组的声明方式是不是很熟悉?看起来就跟Java里面的ArrayList用法差不多,都是在尖括号中间加入数据结构的类型。同理,其他类型的数组变量也能通.过“Array<数据类型>”的方式来声明,像前面介绍的整型数组,其实可以使用类型Array<Int>,以此类推,改造之后的各类型数组变量的声明代码如下所示:
var int_ array :Array<Int> = array0f(1, 2, 3)
var long_ array :Array<Long> = array0f(1, 2,3)
var float_ array : Array<F1oat> = array0f(1.0f, 2.0f, 3.0f)
var double_ array: Array<Doub1e> = array0f(1.0, 2.0,3.0)
var boolean_ array : Array<Boolean> = arrayOf(true, false, true)
var char_ array :Array<Char> = arrayOf('a', 'b', 'c')
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//声明整型数组
var int_array: IntArray = intArrayOf(1, 2, 3, 4);
//也可以按下面方式声明
var int_array2: Array<Int> = arrayOf(1, 2, 3, 4)
tv_integer.setOnClickListener { setArrayStr(int_array2) }
//声明长整型数组
var long_array: LongArray = longArrayOf(1, 2, 3);
var long_array2:Array<Long> = arrayOf(1, 2, 3)
tv_long.setOnClickListener { setArrayStr(long_array2) }
//声明浮点数组
var float_array: FloatArray = floatArrayOf(1.0f, 2.0f, 3.0f);
var float_array2:Array<Float> = arrayOf(1.0f, 2.0f, 3.0f)
tv_float.setOnClickListener { setArrayStr(float_array2) }
//声明双精度数组
var double_array: DoubleArray = doubleArrayOf(1.0, 2.0, 3.0);
var double_array2:Array<Double> = arrayOf(1.0, 2.0, 3.0)
tv_double.setOnClickListener { setArrayStr(double_array2) }
//声明布尔型数组
var boolean_array: BooleanArray = booleanArrayOf(false, true, false);
var boolean_array2:Array<Boolean> = arrayOf(false, true, false)
tv_boolean.setOnClickListener {
var str:String = ""
for (item in boolean_array2) {
str = str + item.toString() + ", "
}
tv_text.text = str }
//声明字符数组
var char_array: CharArray = charArrayOf('a', 'b', 'c');
var char_array2:Array<Char> = arrayOf('a', 'b', 'c')
tv_char.setOnClickListener { var str:String = ""
for (item in char_array) {
str = str + item.toString() + ", "
}
tv_text.text = str }
//声明字符串数组
var string_array: Array<String> = arrayOf("hao", "are", "you");
tv_string.setOnClickListener {
var str:String = ""
var i:Int = 0
while (i<string_array.size) {
str = str + string_array[i] + ", "
//数组元素可以通过下标访问,也可通过get方法访问
//str = str + string_array.get(i) + ", "
i++
}
// for (item in string_array) {
// str = str + item + ", "
// }
tv_text.text = str
}
}
inline fun <reified T : Number> setArrayStr(array: Array<T>) {
var str: String = ""
for (item in array) {
str = str + item.toString() + ",";
}
tv_text.text = str
}
}
2.2数组元素的操作
- (1)对于如何获取数组长度,Java使用.length,而Kotlin使 用size
- (2)对于如何获取指定位置的数组元素,Java通过方括号加下标来获取,比如"int_ array[0]"指的是得到该数组的第一个元素 ; Kotlin也 能通过方括号加下标来获取指定元素,不过Kotlin还拥有get和set两个方法,通过get方法获取元素值,通过set方法修改元素值,看起来就像在操作ArrayList队列。
var str_array: Array<String> = arrayOf("how", "are", "you")
btn_shuzu.setOnClickListener {
var str: String = ""
var i: Int = 0
while (i < str_array.size) {
str = str + str_array[i] + ","
//数组元素可以通过下标访问,也可以通过get方法访问
//str=str+str_array.get(i)
i++
}
btn_shuzu.text = str
}
2.3 字符串
2.3.1 字符串与基本类型的转换
首先要说明的是字符串类型与基本变量类型之间的转换方式,在前面的“2.1.2简单变量之间的转换”中,提到基本数据类型的变量可以通过toString方法转换为字符串类型。反过来,字符串类型又该如何转换为基本变量类型呢?表2-4展示使用Kotlin和Java编码将字符串转换为基本数据类型的对照方式说明。
符串转换目标 | Koin的转换方式 | Java的转换方式 |
---|---|---|
字符串转整型 | 字符串变量的toInt方法 | Integer.parseInt (字符串变量) |
字符串转长整型 | 字符串变量的toLong方法 | Long.parseLonglogpsuong (字符串变量) |
字符串转浮点数 | 字符串变量的toFloat方法 | Float.parseFloat(字符串变量) |
字符串转双精度数 | 字符串变量的toDouble方法 | Double.parseDouble(字符串变量) |
字符串转布尔类型 | 字符串变量的toBoolean方法 | Double.parseBoolean(字符串变量) |
字符串转字符数组 | 字符串变量的toCharArray方法 | 字符串变量的toCharArray方法 |
2.3.2字符串的常用方法
当然,转换类型只是字符串的基本用法,还有更多处理字符串的其他用法,比如查找子串、替换子串、截取指定位置的子串、按特定字符分隔子串等,在这方面Kotlin基本兼容Java的相关方法。对于查找子串的操作,二者都调用indexOf方法;对于截取指定位置子串的操作,二者都调用substring方法;对于替换子串的操作,二者都调用replace方法;对于按特定字符分隔子串的操作,二者都调用split方法。
//2.3.2字符串的常用方法
//查找子串indexOf、截取指定位置子串substring()、替换子串replace()、分隔子串split()、
var origin_str: String = "123456.789"
if (origin_str.indexOf('.') > 0) {
btn_str.text = origin_str.substring(0, origin_str.indexOf('.'))
}
//注意:split()方法返回的时队列,即List<String>
btn_split.setOnClickListener {
var strList: List<String> = origin_str.split('.')
var strResult: String = ""
for (item in strList) {
strResult = strResult + item + ","
}
btn_split.text = strResult
}
//获取指定位置的字符串
btn_get_char.setOnClickListener {
btn_get_char.text = origin_str.get(3).toString()
}
2.3.3 字符串模板及其拼接
kotlin进行了优化,何必引入这些麻烦的格式转换符呢?直接在字符串中加入“$变量名”即可表示此处引用该变量的值,岂不妙哉!
例如:
//2.3.3字符串模板及其拼接
var origin: String = "123456.789"
//模板
btn_format.setOnClickListener { btn_format.text = "字符串模板为:$origin" }
这里要注意,符号$后面跟变量名,系统会自动匹配最长的变量名。比如下面这行代码,打印出来的是变量origin_str的值,而不是origin的值:
例如:
//2.3.3字符串模板及其拼接
var origin_str: String = "123456.789"
//模板
btn_format.setOnClickListener { btn_format.text = "字符串模板为:$origin_str" }
另外,有可能变量会先进行运算,再把运算结果拼接到字符串中。此时,需要用大括号把运算表达式给括起来,具体代码如下所示:
//模板带有计算
btn_format_caculate.setOnClickListener { btn_format_caculate.text = "字符串长度为:${origin_str.length}" }
在上述的Kotlin格式化代码中,美元符号$属于特殊字符,因此不能直接打印它,必须经过转义才可以打印。转义的办法是使用“${'***'}”表达式,
该表达式外层的"${'*** '}"为转义声明,
内层的“***”为需要原样输出的字符串,所以通过表达式“${$'}”即可打印一个美元符号,示例代码如下:
"${'***'}" 打印一个转义字符 -->"${'$'}"--即打印一个$符号
btn_dollar.setOnClickListener { btn_dollar.text = "美元符号:${'$'}$origin" }
2.4 容器
2.4.1 容器的基本操作
与Java类似,Kotlin也拥 有三类基本的容器,分别是集合Set、队列List、映射Map,然后每类容器又分作只读与可变两种类型,这是为了判断该容器能否进行增、删、改等变更操作。Kotlin对变量的修改操作很慎重,每个变量在定义的时候就必须指定能否修改,比如添加val修饰表示该变量不可修改,添加var修饰表示该变量允许修改。至于容器默认为只读容器,如果需要允许修改该容器变量,就需要加上Mutable前缀形成新的容则器,比如MutableSet表示可变集合,MutableList 表示可变队列,MutableMap表 示可变映射,只有可变的容器才能够对其内部元素进行增、删、改操作。
既然集合Set、队列List、映射Map三者都属于容器,那么它们必定拥有相同的容器方法,这些公共方法具体说明如下。
//容器的公共方法
- isEmpty:
- isNotEmpty:
- clear:
- contains:
- iterator:
- count:获取容器包含的元素的个数,也可以通过size属性获取元素数量
另外,Kotlin允许在声明容器变量时就进行初始赋值,例如:
val satelLites: List<String> = listOf("水星", "金星", "地球", "火星", "木星", "土星")
当然,不同容器的初始化方法有所区别,各种容器与其初始化方法的对应关系见表2-5。
Kotlin的容器 | 容器名称 | 容器的初始化方法 |
---|---|---|
只读集合 | Set | setOf |
可变集合 | MutableSet | mutableSetOf |
只读队列 | List | listOf |
可变队列 | MutableList | mutableListOf |
只读映射 | Map | mapOf |
可变映射 | MutableMap | mutableMapOf |
2.4.2 集合Set/MutableSet
集合是一种最简单的容器,它具有以下特性:
(1)容器内部的元素不按顺序排列,因此无法按照下标进行访问。
(2)容器内部的元素存在唯- -性,通过哈希值校验是否存在相同的元素,若存在,则将其覆盖。
因为Set是只读集合,初始化赋值后便不可更改,所以元素变更的方法只适用于可变集合MutableSet,但MutableSet的变更操作尚有以下限制:
(1) MutableSet的add方 法仅仅往集合中添加元素,由于集合是无序的,因此不知道添加的具体位置。
(2) MutableSet没 有修改元素值的方法,一个元素一旦被添加,就不可被修改。
(3) MutableSet的remove方 法用于删除指定元素,但无法删除某个位置的元素,这是因为集合内的元素不是按顺序排列的。
对于集合的遍历操作,Kotlin提供了好几种方式,有熟悉的for-in循环、迭代器遍历,还有新面孔forEach遍历,这三种集合遍历的用法说明如下。
for-in循环
val goodsMutSet: Set<String> = setOf("iphone11", "Mate30", "小米9", "oppo11", "VIVO", "魅族17")
btn_set_for.setOnClickListener {
var desc = ""
for (item in goodsMutSet) {
desc = "${desc}名称:${item}\n"
}
btn_set_for.text = "手机畅销榜包含以下${goodsMutSet.size}手机:\n$desc"
}
Iterator遍历
btn_iterator.setOnClickListener {
var desc = ""
val iterator = goodsMutSet.iterator()
while (iterator.hasNext()) {
val item = iterator.next()
desc = "${desc}名称:${item}\n"
}
btn_iterator.text = "手机畅销榜包含以下${goodsMutSet.size}手机:\n$desc"
}
forEach遍历
btn_forEach.setOnClickListener {
var desc = ""
goodsMutSet.forEach {
desc = "${desc}名称:${it}\n"
btn_forEach.text = "手机畅销榜包含以下${goodsMutSet.size}手机:\n$desc"
}
}
结合以上有关SetMutableSet的用法说明,可以发现集合在实战中存在诸多不足,主要包括以下几点:
(1) 集合不允许修改内部元素的值。
(2)集合无法删除指定位置的元素。
(3) 不能通过下标获取指定位置的元素。
2.4.3 队列List/MutableList
队列是一种元素之间按照顺序排列的容器,它与集合的最大区别在于多了次序管理。不要小看这个有序性,正因为队列建立了秩序规则,所以它比集合多提供了如下功能(注意,凡是涉及增、删、改的,都必须由MutableList来完成) :
(1)队列能够通过get方法获取指定位置的元素,也可以直接通过下标获得该位置的元
素。
(2) MutableList的add方 法每次都是把元素添加到队列末尾,也可指定添加的位置。
(3) MutableList的set方法允许替换或者修改指定位置的元素。
(4)MutableList的removeAt方 法允许删除指定位置的元素。
(5) 队列除了拥有跟集合一样的三种遍历方式(for-in循环、 迭代器遍历、forEach遍历)外,还多了一种按元素下标循环遍历的方式,具体的下标遍历代码例子如下:
val goodsMutList: List<String> = listOf("iphone11", "Mate30", "小米9", "oppo11", "VIVO", "魅族17")
btn_list_forin.setOnClickListener {
var desc = ""
//indices是队列的下标数组。如果队列大小为10,下标数组的取值为0-9
for (i in goodsMutList.indices) {
val item = goodsMutList[i]
desc = "${desc}名称:${item}\n"
}
btn_list_forin.text = "手机畅销榜包含以下${goodsMutList.size}手机:\n$desc"
}
(6) MutableList提 供了sort系列方法用于给队列中的元素重新排序,其中sortBy方法表示按照指定条件升序排列,sortByDescending方 法表示按照指定条件降序排列。下 面是一个给队列排序的代码例子(含升序和降序) :
var sortAsc = true
btn_list_sort.setOnClickListener {
//
if (sortAsc) {
goodsMutList.sortedBy { it.length }
} else {
goodsMutList.sortedByDescending { it.length }
}
var desc = ""
for (item in goodsMutList) {
desc = "${desc}名称:${item}\n"
}
btn_list_sort.text = "手机畅销榜已按照${if (sortAsc) "升序" else "降序"}重新排序:\n$desc"
sortAsc = !sortAsc
}
2.4.4 映射Map/MutableMap
映射内部保存的是一组键值对(Key-Value) ,也就是说,每个元素都由两部分构成,第一部分 是元素的键,相当于元素的名字:第二部分是元素的值,存放着元素的详细信息。元素的键与值是一一对应的关系,相同键名指向的键值是唯一的, 所以映射中每个元素的键名各不相同,这个特性使得映射的变更操作与队列存在以下不同之处(注意,增、删操作必须由MutableMap来完成) :
(1)映射的containsKey方法判断是否存在指定键名的元素,containsValue方法判断是否存在指定键值的元素。
(2) MutableMap的put方 法不单单是添加元素,而是智能的数据存储。每次调用put方法时,映射会先根据键名寻找同名元素,如果找不到就添加新元素,如果找得到就用新元素替换旧元素。
(3) MutableMap的remove方 法是通过键名来删除元素的。
(4)调用mapOf和mutableMapOf方 法初始化映射时,有两种方式可以表达单个键值对元素,其一是采取“键名to键值”的形式,其二是采取Pair配对方式,形如“Pair(键名,键值)”。下面是这两种初始化方式的代码例子:
//初始化
//1.to方式映射
var goodMap: Map<String, String> =
mapOf("苹果" to "iphone11", "华为" to "huawei30", "小米" to "xiaomi9", "欧珀" to "OPPO", "魅族" to "meizu16")
//2.Pair方式初始化映射
var goodsMutMap: MutableMap<String, String> = mutableMapOf(
Pair("苹果", "iphone11"),
Pair("华为", "mate30"), Pair("欧珀", "OPPO"), Pair("小米", "xiaomi6"), Pair("魅族", "meizu16")
)
映射的遍历与集合类似,也有for-in循环、迭代器遍历、forEach遍 历三种遍历手段。但是由于映射的元素是一一个键值对,因此它的遍历方式与集合稍有不同,详述如下:
for-in
btn_map_forIn.setOnClickListener {
var desc = ""
//使用for-in语句循环取出映射中的每条记录
for (item in goodsMutMap) {
//item.key表示该配对的键,即厂家名称;item.value表示该配对的值,即手机名称
desc = "${desc}厂家;${item.key},名称:${item.value}\n"
}
btn_map_forIn.text = "手机畅销榜包含以下${goodsMutMap.size}款手机:\n$desc"
}
迭代器遍历
btn_map_iterator.setOnClickListener {
var desc = ""
val iterator = goodsMutMap.iterator()
while (iterator.hasNext()) {
val item = iterator.next()
desc = "${desc}厂家;${item.key},名称:${item.value}\n"
}
btn_map_iterator.text = "手机畅销榜包含以下${goodsMutMap.size}款手机:\n$desc"
}
forEach遍历
btn_map_forEach.setOnClickListener {
var desc = ""
goodMap.forEach { key, value ->
desc = "${desc}厂家;${key},名称:${value}\n"
}
btn_map_forEach.text = "手机畅销榜包含以下${goodsMutMap.size}款手机:\n$desc"
}