前边就不用过多的介绍了,自从Google选择Kotlin,有一波开发者开始学习了。下边记录一下第一次学习Kotlin的一些笔记。
1、变量及常量的定义
说一个var和val的区别
var是定义一个变量,以后这个值是可以变的
val是定义一个常量,在以后的操作过程中,这个值是不能变的.
val a: Int = 1 // 立即初始化
val b = 2 // 推导出Int型
val d = 2.357 // 小数,默认为doulbe类型
var c: Int? = null // 当没有初始化值时必须声明类型
2、元组
这个貌似是个新鲜的东西,之前在java语言里边是没有这个东西的。看一下怎么用。
/**
* 元组 三元元组
*/
var (name, move, number) = kotlin.Triple("小米", "左", 3)
LogUtils.Loge("${name}向${move}边移动了${number}步")
/**
* 二元元组
*/
var (name1, move2) = Pair("小明", "右")
LogUtils.Loge("${name1}向${move2}边移动了5步")
/**
* 二元元组
*/
var move3 = Pair("小红", "前")
LogUtils.Loge("${move3.first}向${move3.second}边移动了10步")
然后看一下控制台的输出的效果:
11-16 13:51:31.648 3728-3728/com.example.lql.kotlindemo E/###: 小米向左边移动了3步###
11-16 13:51:31.648 3728-3728/com.example.lql.kotlindemo E/###: 小明向右边移动了5步###
11-16 13:51:31.648 3728-3728/com.example.lql.kotlindemo E/###: 小红向前边移动了10步###
定义一个三元元组使用Triple关键字,定义一个二元元组使用Pair关键字。如果不想给元组定义多个变量,可以使用第三个写法中的方式,然后在使用元组中的参数的时候,使用"变量名.first" .
嗯嗯,这里大家还可以看到一个骚操作,如果要把字符串和变量拼接起来,是用${变量名}来在字符串中拼接。
3、集合
在Kotlin中集合分为三种形式:
Set: 无序不重复、List:有序可重复,索引从0开始、Map(映射):无序不重复,键值对
3.1先看Set、看代码:
//定义一个不可变的Set集合
var mStringSet1: Set<String> = setOf("E", "F", "B", "C", "A", "D", "F", "B")
//定义一个可以变的Set集合
var mStringSet2: Set<String> = mutableSetOf("E", "F", "B", "C", "A", "Z")
//创建一个空的Set集合
var mStringSet3: Set<String> = emptySet()
LogUtils.Loge("数量:" + mStringSet1.count())
LogUtils.Loge("是否为空:" + mStringSet3.isEmpty())
for (item in mStringSet1) {
LogUtils.Loge(item + ">>>mStringSet1")
}
//是否包含某个元素
LogUtils.Loge("判断是否包含某个元素:" + mStringSet1.contains("A"))
//是否包含某个集合
LogUtils.Loge("判断是否包含某个集合:" + mStringSet1.containsAll(mStringSet2))
//转换成list
val toTypedArray = mStringSet1.toTypedArray()
for (s in toTypedArray) {
LogUtils.Loge("集合转换成数组:" + s)
}
//集合之间的操作
val intersect = mStringSet1.intersect(mStringSet2)
LogUtils.Loge("交集:" + intersect)
val union = mStringSet1.union(mStringSet2)
LogUtils.Loge("全集:" + union)
val subtract = mStringSet1.subtract(mStringSet2)
LogUtils.Loge("差集:" + subtract)
val minus = mStringSet1.minus(mStringSet2)
for (minus1 in minus) {
LogUtils.Loge("补集:" + minus1)
}
//转换成ToMutableSet
val toMutableList = mStringSet2.toMutableList()
for (s in toMutableList) {
LogUtils.Loge("toMutableList:" + s)
}
//MutableSet:大小可变的集合
//增加一个
toMutableList.add("K")
for (s in toMutableList) {
LogUtils.Loge("新增加了一个:" + s)
}
//增加一堆
toMutableList.addAll(mStringSet1)
for (s in toMutableList) {
LogUtils.Loge("新增加了一堆:" + s)
}
//删除第0个
toMutableList.removeAt(0)
for (s in toMutableList) {
LogUtils.Loge("删除第0个:" + s)
}
//删除某一个
toMutableList.remove("K")
for (s in toMutableList) {
LogUtils.Loge("删除某一个:" + s)
}
set集合是不可重复的且无序的集合,但是在上述代码mStringSet1集合中出现了重复的元素,大家可以看一下效果,虽然在初始化的时候,集合中包含重复元素,但是在使用的时候是不会出现重复元素的。看一下控制台输出:
11-16 14:05:28.898 4579-4579/com.example.lql.kotlindemo E/###: E>>>mStringSet1###
11-16 14:05:28.898 4579-4579/com.example.lql.kotlindemo E/###: F>>>mStringSet1###
11-16 14:05:28.898 4579-4579/com.example.lql.kotlindemo E/###: B>>>mStringSet1###
11-16 14:05:28.898 4579-4579/com.example.lql.kotlindemo E/###: C>>>mStringSet1###
11-16 14:05:28.898 4579-4579/com.example.lql.kotlindemo E/###: A>>>mStringSet1###
11-16 14:05:28.898 4579-4579/com.example.lql.kotlindemo E/###: D>>>mStringSet1###
然后在set集合中咱们可以求两个set集合交集、差集、并集、补集。具体的操作在上述代码中有体现,大家可以去自行试试效果。
还有一点,在初始话set集合的时候,是一个不可变的集合,在后续操作中不能对集合进行增加、删除元素等操作。如果我们想要去操作集合,就要调用集合的.toMutableList()方法,然后再去对集合进行add()、addAll()、remove()等操作。
3.2 再看List集合:
list集合是一个有序,可重复的集合。
所以在list集合比set集合多了拿到第几个元素的方法,调用 stationsList[index])或者stationsList.get(index)就可以拿到集合中的第index个元素。
还有一个集合的切割方法: stationList3.subList(2, 4)或者stationList3.slice(2..3)
解释一下两个方法的:
subList()方法,包含第2个元素和第3个元素但是不包含第4个元素
slice()方法,包含第2和第3个元素
然后其他的对集合操作的方法和Set集合类似,这里就不赘述了。
//定义一个数组
var stationsList = arrayOf("石家庄", "北京", "南京", "上海", "苏州", "上海")
for (s in stationsList) {
LogUtils.Loge("stationList:" + s)
}
//创建一个有默认值的数组
var stationList2 = Array(20, { "默认站的名字" })
for (s in stationList2) {
LogUtils.Loge("默认名称:stationList2:" + s)
}
//创建一个从1--100的数组
var oneToHundred = Array(100, { i -> i + 1 })
for (s in oneToHundred) {
LogUtils.Loge("0到100》oneToHundred:" + s)
}
//元素的个数 判断是否为空
if (oneToHundred.isNotEmpty()) {
LogUtils.Loge(oneToHundred.count().toString())
}
//获取某一个数据
LogUtils.Loge("站名的第一个" + stationsList.first())
LogUtils.Loge("站名的最后一个" + stationsList.last())
LogUtils.Loge("前两个" + stationsList.component1() + stationsList.component2())
LogUtils.Loge("第两个" + stationsList[2 - 1])
LogUtils.Loge("第两个" + stationsList.get(2 - 1))
//筛选重复(把重复的去掉)
var stationList3 = stationsList.distinct()
for (s in stationsList) {
LogUtils.Loge("不重复的数组" + s)
}
//把一个数组转化成集合
val toSet = stationsList.toSet()
for (s in toSet) {
LogUtils.Loge("不重复的集合" + s)
}
//数组切割 从第二个到第三个,包含前边,不包含后边
val subList = stationList3.subList(2, 4)
for (s in subList) {
LogUtils.Loge("截取数组:" + s)
}
//切割数组 从第二个到第三个,包含前边,也包含后边
val slice = stationList3.slice(2..3)
for (s in slice) {
LogUtils.Loge("切割数组:" + s)
}
//#################################################以上是不可变的数组#############################
//定义大小可变的数组
val mutableList2 = mutableListOf("a", "b", "c")
for (s in mutableList2) {
LogUtils.Loge("可变数组:" + s)
}
//增加一个
mutableList2.add(2, "e")
for (s in mutableList2) {
LogUtils.Loge("可变数组,新增加一个:" + s)
}
val mutableList1 = mutableListOf("1", "2", "3")
//增加一堆
mutableList2.addAll(mutableList1)
for (s in mutableList2) {
LogUtils.Loge("可变数组,新增加一堆:" + s)
}
//移除第几个
mutableList2.removeAt(0)
for (s in mutableList2) {
LogUtils.Loge("可变数组,移除第几个:" + s)
}
//移除某一个
mutableList2.remove("e")
for (s in mutableList2) {
LogUtils.Loge("可变数组,移除某一个:" + s)
}
for (index in mutableList2.indices) {
LogUtils.Loge("换种写法写循环:" + mutableList2.get(index))
}
val list3 = ArrayList<String>()
list3.add("李")
list3.add("小")
list3.add("米")
list3.remove("李")
list3.add(0, "牛")
list3.removeAt(1)
for (item in list3) {
LogUtils.Loge("List3集合:" + item)
}
3.3 最后Map集合:
Map集合和java中的Map相差不大,具体用法可以参照下边的代码。
//创建一个map
var stationMap = mapOf(Pair("shijiazhuang", "石家庄"), Pair("nanjing", "南京"),
Pair("suzhou", "苏州"), Pair("shanghai", "上海"), Pair("zhangjiakou", "张家口")
, Pair("taiyuan", "太原"), Pair("tianjin", "天津"))
LogUtils.Loge("map数量:" + stationMap.count())
LogUtils.Loge("map是否位空:" + stationMap.isEmpty())
//根据key获取values
LogUtils.Loge(stationMap.get("tianjin"))
//获取所有的key
val keys = stationMap.keys
for (s in keys) {
LogUtils.Loge("所有的key:" + s)
}
//获取所有的values
val values = stationMap.values
for (s in values) {
LogUtils.Loge("所有的values:" + s)
}
val toMutableMap = stationMap.toMutableMap()
toMutableMap.remove("shijiazhuang")
for (mutableEntry in toMutableMap) {
LogUtils.Loge("移除某一个:" + mutableEntry)
}
toMutableMap["nanjing"] = "南京市"
for (mutableEntry in toMutableMap) {
LogUtils.Loge("根据key修改values:" + mutableEntry)
}
toMutableMap["cangzhou"] = "沧州"
for (mutableEntry in toMutableMap) {
LogUtils.Loge("这样能新增一个:" + mutableEntry)
}
4、函数/方法
4.1基本方法
//基本函数
fun init() {
/**
* 调用一个方法
*/
LogUtils.Loge("调用一个方法:" + makeIntData(1))
LogUtils.Loge("调用求和方法:" + sum(1, 2).toString())
LogUtils.Loge("调用求和方法,第二个参数不传递:" + sum(1).toString())
LogUtils.Loge("调用求和方法,可变参数,第一个:" + sum1(1, 2, 3, 4, 5).toString() + ",第二个:" + sum1(1, 2, 3))
var intArrayOf = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8)
LogUtils.Loge("调用求和方法,可变参数,也可以穿一个数组进去:" + sum1(*intArrayOf).toString())
}
/**
* 定义一个入参为int类型的,返回值为String 类型的方法
*/
private fun makeIntData(number: Int): String {
return (number + 1).toString()
}
/**
* 定义一个入参为两个int类型 ,第一个必选,第二个不传的时候默认为0,返回只为int 类型,但是可以为null
* 以及三元运算符的使用
*/
private fun sum(number: Int?, number1: Int = 0): Int? {
// if (number != null) {
// return number + number1
// } else {
// return null
// }
return if (number != null) number + number1 else null
}
/**
* 定义一个可变参数
*/
private fun sum1(vararg x: Int): Int {
var sumNumber = 0
for (i in x) {
sumNumber += i
}
return sumNumber
}
看一下输出的效果:
11-16 14:35:04.368 4579-4579/com.example.lql.kotlindemo E/###: 调用一个方法:2###
11-16 14:35:04.368 4579-4579/com.example.lql.kotlindemo E/###: 调用求和方法:3###
11-16 14:35:04.368 4579-4579/com.example.lql.kotlindemo E/###: 调用求和方法,第二个参数不传递:1###
11-16 14:35:04.368 4579-4579/com.example.lql.kotlindemo E/###: 调用求和方法,可变参数,第一个:15,第二个:6###
11-16 14:35:04.368 4579-4579/com.example.lql.kotlindemo E/###: 调用求和方法,可变参数,也可以穿一个数组进去:36###
4.2高阶函数
高阶函数:
1、参数或者返回值的类型是函数型
函数型:(参数)--》返回值
lambda: 一种无名函数的简写{ (参数)--》函数执行语句}
其他语言称为闭包,即有能力访问其自身范围外的变量
2 、描述任务的结果,而不是使用循环详细推算
map:常用于对集合类型的元素类型整体元转
其lambda中的参数的约定称为it
//想要把数字转化为汉字
val a = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val b = a.map { "第${it}" }
for (s in b) {
LogUtils.Loge("整数转换位字符串" + s)
}
//闭包
//filter:对集合类型进行筛选
//把偶数筛选出来,然后求和
var sum = 0
val c = a.filter {
it % 2 == 0
}.forEach {
sum += it
LogUtils.Loge("闭包中的:" + sum)
}
//分组
val groupBy = a.groupBy { it % 2 == 0 }
LogUtils.Loge("groupBy" + groupBy)
5、控制流 for\while\when
这个就没啥好说的了,大家看下代码,然后看一下输出的结果,就明白是啥意思,记住具体的写好就好了。
//循环中的控制 : continue 结束本次循环 ,break结束整个循环
var stringList = arrayOf("小牛", "太阳", "鹈鹕", "黄蜂" )
//依次操作一个序列(如集合类型)中的每一项,执行次数是可预测的
for (s in stringList) {
LogUtils.Loge("循环:" + s)
}
//重复执行
for (a in 0..10) {
if (a == 5) {
continue
}
LogUtils.Loge("一直在重复执行" + a)
}
//while:循环执行操作,直到条件不成立.例子:计算从1开始,加到多少,和是5050
var sum = 0//和
var number = 1//起始数
var timer = 0//次数
while (sum < 5050) {
if (number == 5) {
break
}
timer += 1
number += 1
sum += number + 1
LogUtils.Loge("while:循环" + timer)
}
var a = 10
if (a == 10)
LogUtils.Loge("a等于10")
else
LogUtils.Loge("a不等于10")
LogUtils.Loge(if (a == 10) "a等于10" else "a!=10")
//在wen语句中,满足了一个条件,就不去执行下边的了
when (a) {
// in 0..11 -> {
// LogUtils.Loge("a在0到11之间")
// }
(20 - 11) -> {
LogUtils.Loge("a==10")
}
is Int->{
LogUtils.Loge("a是Int类型")
}
else -> {
LogUtils.Loge("a不在0到11之间")
}
}
然后看一下输出的结果:
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 循环:小牛###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 循环:太阳###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 循环:鹈鹕###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 循环:黄蜂###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行0###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行1###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行2###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行3###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行4###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行6###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行7###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行8###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行9###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: 一直在重复执行10###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: while:循环1###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: while:循环2###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: while:循环3###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: while:循环4###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: a等于10###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: a等于10###
11-16 14:56:17.408 4994-4994/com.example.lql.kotlindemo E/###: a是Int类型###
6、面向对象编程
这里介绍类的定义、属性、方法以及继承、数据类、枚举类、对象生命和表达式的写法:
private fun init() {
var mBook1 = ShoppingBook("如何购物", 50)
var mBook2 = FoodBook("吃东西", 20, "food")
LogUtils.Loge(mBook1.toString())
LogUtils.Loge(mBook2.toString())
LogUtils.Loge("mBook1.colors" + mBook1.colors)
LogUtils.Loge("mBook1.address" + mBook1.address)
LogUtils.Loge("mBook1.number" + mBook1.number)
LogUtils.Loge("mBook1.newPrice" + mBook1.newPrice)
mBook1.colors = "绿色"
LogUtils.Loge("mBook1.colors" + mBook1.colors)
LogUtils.Loge("mBook1.address" + mBook1.address)
LogUtils.Loge("mBook1.number" + mBook1.number)
LogUtils.Loge("mBook1.newPrice" + mBook1.newPrice)
mBook1.cook()
mBook2.cook()
//数据类
var mUser = User("小米", "123456")
LogUtils.Loge(mUser.toString())
//复制
var mUser2 = mUser.copy(password = "123")
LogUtils.Loge(mUser2.toString())
//数据类对象的结构
var (name, password) = mUser
LogUtils.Loge("username:$name,$password")
//列举熟悉
LogUtils.Loge("${mUser.component1()}${mUser.component2()}")
LogUtils.Loge("枚举类:" + SexType.values().joinToString())
val sizeOrdinal = Size.valueOf("M").ordinal
val sizeName = Size.valueOf("M").name
LogUtils.Loge("带有构造器的枚举类:" + sizeOrdinal + sizeName)
val joinToString = Size.values().joinToString { it.name + ":" + it.height }
LogUtils.Loge("带有构造器的枚举类:" + joinToString)
//对象表达式
val baako = object : Chinese("Baako Zaid") {
override var skin = "black"
}
LogUtils.Loge(baako.skin)
//纯对象表达式:是临时用,无需继承任何类
val temParking = object {
var x = 100
}
//封装一个类
NetWorkRequestManager.register()
//伴生方法与类的关联性强
IDCard.creat()
}
/**
* 伴生对象:一般用于创建一个类的实例的“工厂”方法
* 相当于java的静态成员
*/
class IDCard {
companion object {
fun creat() = IDCard()
}
}
//对象声明
object NetWorkRequestManager {
fun register() {
LogUtils.Loge("连接网络")
}
}
/**
* 对象表达式
*/
open class Chinese(var name: String) {
open var skin = "yellow"
}
/**
* 定义一个书的实体
* 关键字open ,如果一个类想要被集成,需要在class前加上open关键字
*/
/**
* 访问修饰符:
* private
* protected 仅子类可见
* internal 当前模块内可见
* public
*/
open class Book constructor(var name: String, var price: Int, var type: String) {
//普通属性
open var colors: String = "红色"
var newPrice: Int = 0
//组合属性
var address: String = ""
get() {
when (this.colors) {
"红色" -> {
return "石家庄"
}
else -> {
return "其他"
}
}
}
//组合属性也可以影响其他属性
var number: Int
get() {
when (this.address) {
"石家庄" -> {
return 100
}
else -> {
return 200
}
}
}
set(value) {
when (value) {
in 0..199 -> {
newPrice = 100
}
else -> {
newPrice = 200
}
}
}
//类中的方法
open fun cook() {
val menu = arrayOf("番茄炒蛋", "炒土豆", "小米粥")
val reduce = menu.reduce { s1, s2 -> s1 + "," + s2 }
LogUtils.Loge("类中的方法:${reduce}")
}
}
/**
* 类的继承
*/
class ShoppingBook(name: String, price: Int, type: String = "shopping") : Book(name, price, type) {
var content = "教你如何购物"
override fun cook() {
super.cook()
var menu = arrayOf("毛血旺", "烤鱼")
val reduce = menu.reduce { s1, s2 -> s1 + "," + s2 }
LogUtils.Loge("子类继承父类的方法:${reduce}")
}
}
/**
* 类的继承
*/
class FoodBook(name: String, price: Int, type: String) : Book(name, price, type) {
var content = "如何吃东西才健康"
//在子类中如果要重写父类的属性,要在父类属性中添加open关键字
override var colors = "食物黄色"
}
/**
* 数据类
*/
data class User(var username: String, var password: String)
/**
* 枚举类
*/
enum class SexType {
男, 女
}
/**
* 带有构造器的枚举类
*/
enum class Size(val height: Int) {
S(150), M(160), L(170), XL(180)
}
7、异常处理以及类型转换
7.1异常处理:
分为两种方式:一种是重要的异常,对程序产生重要影响的,我们要捕获异常,并且处理一下。
第二种是不重要的,在java中是抛出异常,这里抛出异常的写法和java不太一样。
具体看代码:
//捕获异常
try {
"g".toInt()
} catch (e: Exception) {
LogUtils.Loge(e.toString())
}
//抛出异常
val a: Int? = try {
"g".toInt()
} catch (e: Exception) {
null
}
LogUtils.Loge(a.toString())
Log:
11-16 15:09:47.668 4994-4994/com.example.lql.kotlindemo E/###: java.lang.NumberFormatException: Invalid int: "g"###
11-16 15:09:47.678 4994-4994/com.example.lql.kotlindemo E/###: null###
7.2类型检查和类型转换:
这里值得说的是类型转换,在kotlin中分为强制类型转换和安全转换,
比如在代码中吧变量C转换成String类型,如果你非常确定C是一个String,那么你就可以使用强制类型转换。但是如果你不确定C是一个String,那么你可能就需要安全转换了。在安全转换中,如果出现错误,最后拿到的值是一个null.但是不影响程序的运行。
val a = 5
val b = 6
val c = if (a > b) "大于" else a - b
//类型检查
if (c is String) {
LogUtils.Loge("长度" + c.length)
}
if (c !is String) {
LogUtils.Loge("整数" + c)
}
//类型转换
try {
//强制转换
var d = c as String
LogUtils.Loge("强制转换:" + d)
} catch (e: Exception) {
LogUtils.Loge("强制转换报错了" + e.toString())
}
//安全转换
var e = c as? String
LogUtils.Loge("安全转换:" + e)
Log:
11-16 15:09:47.678 4994-4994/com.example.lql.kotlindemo E/###: 整数-1###
11-16 15:09:47.678 4994-4994/com.example.lql.kotlindemo E/###: 强制转换报错了java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String###
11-16 15:09:47.678 4994-4994/com.example.lql.kotlindemo E/###: 安全转换:null###
好了,先写这些。在下一篇中介绍泛型、接口以及扩展部分的内容。
因为是刚刚开始学习Kotlin,可能对某些概念和语法认识不足,如有错误,希望大家能给予指正!
网友评论