Kotlin中使用var、val来声明对象,区别在于:
var(可变变量):在程序中可更改使用var关键字声明的变量的值。
val(不可变变量):不能改变使用val关键字声明的变量的值,可简单理解为常量定义。
var data=“mmp”
val data2= 200
val data3= true
//变量通常不需要声明类型,编译器会根据数值推断数据类型
var data4:String = “呵呵哒”
kotlin数据类型:
数字:
字符:Char 通常用‘单引号’来表示
布尔:Boolean true/false
数组:Array [“fdsff”,“fdsff”,“fdsff”,“fdsff”]
字符串:String “字符串”
数据类型转换:
在Kotlin中,不支持将较小数据类型隐式转换为较大数据类型(在java中支持)。 例如,Int不能分配转换为Long或Double
要进行转换必须通过显式的方法:
var d = 2
var d2:Long = d.toLong()
转换方法:
toByte()、toShort()、toInt()、toLong()、toFloat()、toDouble()、toChar()、toString()
运算符
算数运算符基本上跟java等主流编程语言保持一致
关系运算符
赋值运算符
一元运算符
不同于一般语言中条件判断使用switch,在kotlin中使用then来实现
var number = 4
when(number) {
1 -> println("One")
2 -> println("Two")
3 -> println("Three")
4 -> println("Four")
5 -> println("Five")
else -> println("invalid number")
}
也可以这样,类似于java中的case穿透
when (test) {
0, 1, 2 -> toast("我是0或者1或者2")
3, 4, 5 -> {
toast("输出结果${3 + 4 + 5}")
}
else -> {
toast("不是0,1,2,3,4,5")
}
}
还可以这样:
when (i) {
in 0..3 -> toast("我是0到3之间的值")
in 4..6 -> {
toast("我是4到6之间的值")
}
!in 7..8 -> {
toast("我不是7到8之间的值")
}
else -> {
toast("else")
}
}
在这里在说一下三目运算符:
java中的语法
条件判断语句 ? “结果为true” : “结果为false”;
kotlin中的语法
if(条件判断语句) “结果为true” else “结果为false”
kotlin中for循环的用法,它遍历数组,范围,集合或提供迭代的任何内容
for (item in collection){
// 循环的主体
}
如果想要基于下标的循环的话:
for(item in marks.indices) {
println("marks[$item]: "+ marks[item])
}
Kotlin函数
在此先说明一下,在kotlin中,万物皆对象,大家都继承自Any,类似于java中的Object 。
在kotlin中,函数使用fun关键字来标识
类似于java,在kotlin类中,有一个main方法
fun main(args: Array){
}
kotlin方法的简单定义方法如下
fun functionName():返回值类型{
// 函数体
}
//如果函数没有返回值 则默认返回Unit:
fun functionName():Unit{
// 函数体
}
Unit可省略
fun functionName(){
// 函数体
}
//函数带返回值的例子:
fun add(value: Int, value2:Int): Int{
val result = value+value2
return result
}
-----------------------------
在函数定义中,可以为参数设置默认值,也可以根据参数名称去设置命名参数
fun run(num:Int= 5, latter: Char ='x'){
print("parameter in function definition $num and $latter")
}
以上定义了num,latter两个函数,并且给函数设置了默认值,那么一下调用方式都是正确的:
run()
run(3)
run(latter='X')
Lambda是一个没有名字的函数。 Lambda是用花括号{}定义的,它将变量作为参数(如果有的话)和函数体。 函数体在变量(如果有)之后写入,后跟 -> 运算符。
lambda的语法:l
{ variable -> body_of_function}
fun main(args: Array){
addNumber(5,10)
}
fun addNumber(a: Int, b: Int){
val add = a + b
println(add)
}
用lambda写法的话就是
fun main(args: Array){
val myLambda: (Int) -> Unit= {s: Int -> println(s) } //lambda function
addNumber(5,10,myLambda)
}
fun addNumber(a: Int, b: Int, mylambda: (Int) -> Unit ){
//high level function lambda as parameter
val add = a + b
mylambda(add) // println(add)
}
高阶函数
接受函数作为参数或返回函数或可以同时执行这两个函数的函数。 意味着,可以将函数作为参数传递给其他函数,而不是将Int,String或其他类型作为参数传递给函数
fun myFun(org: String,portal: String, fn: (String,String) -> String): Unit {
val result = fn(org,portal)
println(result)
}
fun main(args: Array){
val fn:(String,String)->String={org,portal->"$org develop $portal"}
myFun("yiibai.org","yiibai.com",fn)
}
上边的例子中定义了三个参数,其中fn也作为一个参数传入了,
他也有两个参数,并且无返回值。在调用的时候先定义了fn函数然后
将它作为函数传入了myFun
Array数组
数组是Int,String等类似数据类型的集合。Kotlin中的数组本质上是可变的,具有固定大小,这意味着可以对数组元素执行读写操作
基本方法
1:arrayOf(),
2:intArrayOf(),charArrayOf(),booleanArrayOf(),longArrayOf(),shortArrayOf(),byteArrayOf()
基本上分为这么两大类,第二类望文生义不多做解释,关键在第一类
var myArray1 = arrayOf(1,10,4,6,15)
var myArray2 = arrayOf(1,10,4,6,15)
val myArray3 = arrayOf("Ajax","Prake","Michel","John","Curry")
var myArray4= arrayOf(1,10,4, "Ajax","Prake")
我的理解,如果不带泛型,默认的泛型就是Any,带了泛型那么数组中的元素就有了完全相同的数据类型。
val array2 = arrayOf(11,12,13,14)
//修改及获取数据
array2.set(0,5)
array2[2] = 6
println(array2.get(0))
println(array2[2])
//初始化一个大小为5的数组,默认值为0并遍历元素
var myArray = Array(5){0}
字符串的属性与函数
属性:
length: Int 它返回字符串序列的长度。
indices: IntRange 它返回当前char序列中有效字符索引的范围。
lastIndex: Int 它返回char序列中最后一个字符的索引
常用函数:
String类表示char类型的数组。 字符串是不可变的,这意味着长度和元素在创建后不能更改,Array的一些方法字符串也可以使用,比如:
Kotlin中的异常捕获Exception
fun main(args: Array){
try {
val a = IntArray(5)
a[5] = 10 / 0
} catch (e: ArithmeticException) {
println("arithmetic exception catch")
} catch (e: ArrayIndexOutOfBoundsException) {
println("array index outofbounds exception")
} catch (e: Exception) {
println("parent exception class")
} finally {
// optional finally block
}
}
Kotlin可空和非可空类型
Kotlin null安全性是一种消除代码中空引用风险的过程。 如果Kotlin编译器发现任何null参数
而仍然执行null引用相关语句,则会立即抛出NullPointerException。
Kotlin类型系统区分可以保持null(可空引用)和不能保持null(非null引用)的引用。
通常,String类型不可为null。 要创建保存null值的字符串,必须通过放置一个?来明确
定义它们。 例如,在String后面使用:String?
//添加了?修饰的变量允许为空,如果没有添加则不能为空,**在kotlin与java混用的时候尤其要注意这一点**
var str1: String? = "hello"
str1 = null // ok
var str1: String = "hello"
str1 = null // error
使用is来智能转换
fun main(args: Array){
val obj: Any = "变量obj自动转换为此范围内的String"
if(obj is String) {
// No Explicit Casting needed.
println("obj不是字符串")
}else{
println("字符串的长度是:${obj.length}")
}
}
不安全的转换操作符:as
有时无法转换变量并抛出异常,这称为不安全转换。 不安全的强制转换由中缀运算符执行。
可以为空的字符串(String?)不能转换为非null字符串(String),这会引发异常。
Kotlin安全转换操作符:as?
Kotlin提供安全转换操作符:as?安全地转换成一种类型。 如果无法进行转换,则返回null,而不是抛出ClassCastException异常。
fun main(args: Array){
val location: Any = "Kotlin"
val safeString: String? = location as? String
val safeInt: Int? = location as? Int
println(safeString)
println(safeInt)
}
Kotlin提供称为Elvis运算符(?:)的高级运算符,即使条件表达式为空,也返回非空值。 以上if…else运算符可以使用Elvis运算符表示如下:
fun main(args: Array){
var str: String? = null
var str2: String? = "May be declare nullable string"
var len1: Int = str ?.length ?: -1
var len2: Int = str2 ?.length ?: -1
println("Length of str is ${len1}")
println("Length of str2 is ${len2}")
}
//lvis运算符将表达式返回?: -1。 (str ?.length)如果它不为null,否则它将表达式返回?:, 即-1。
//仅当左侧返回null时,才会评估Elvis运算符的右侧表达式。
//当Kotlin抛出并返回一个表达式时,它们也可以在Elvis运算符的右侧使用。 这可以用于检查函数参数:
funfunctionName(node: Node): String? {
val parent = node.getParent() ?: return null
val name = node.getName() ?: throw IllegalArgumentException("name expected")
---------------------类似于三目运算符-------------------
}
Kotlin Elvis运算符使用throw和return表达式
fun main(args: Array){
val fruitName: String = fruits()
println(fruitName)
}
fun fruits(): String{
val str: String? ="abc"
val strLength: Int = if(str!= null) str.length else -1
val strLength2: Int = str?.length ?: -1
var string = "str = $str\n"+
"strLength = $strLength\n"+
"strLength2 = $strLength2\n\n"
fun check(textOne: String?, textTwo: String?): String?{
val textOne = textOne ?: return null
val textTwo = textTwo ?: IllegalArgumentException("text exception")
return "\ntextOne = $textOne\n"+
"textTwo = $textTwo\n"
}
string += "check(null,\"mango\") = ${check(null,"mango")}\n" +
"check(\"apple\",\"orange\") = ${check("apple","orange")}\n"
return string
}
Kotlin集合
**1.**List 是一个有序集合,可通过索引(反映元素位置的整数)访问元素。元素可以在 list 中出现多次。
列表的一个示例是一句话:有一组字、这些字的顺序很重要并且字可以重复。
**2.**Set 是唯一元素的集合。它反映了集合(set)的数学抽象:一组无重复的对象。一般来说 set 中元
素的顺序并不重要。例如,字母表是字母的集合(set)。
**3.**Map(或者字典)是一组键值对。键是唯一的,每个键都刚好映射到一个值。值可以重复。map 对
于存储对象之间的逻辑连接非常有用,例如,员工的 ID 与员工的位置
Kotlin 标准库提供了基本集合类型的实现: set、list 以及 map。 一对接口代表每种集合类型:
一个 只读 接口,提供访问集合元素的操作。
>>>>SET/MAP/LIST
一个 可变 接口,通过写操作扩展相应的只读接口:添加、删除和更新其元素。
>>>>MutableSet/MutableList/MutableMap
请注意,更改可变集合不需要它是以 var 定义的变量:写操作修改同一个可变集合对象,
因此引用不会改变。 但是,如果尝试对 val 集合重新赋值,你将收到编译错误。
val numbers = mutableListOf(“one”, “two”, “three”, “four”)
numbers.add(“five”) // 这是可以的
//numbers = mutableListOf(“six”, “seven”) // 编译错误
(1)Collection 是集合层次结构的根。此接口表示一个只读集合的共同行为:
检索大小、检查一个项的成员等等。 Collection 继承自 Iterable 接口,
它定义了迭代元素的操作。可以使用 Collection 作为适用于不同集合类型的函数的参数。
对于更具体的情况,请使用 Collection 的继承者: List 与 Set。
(2)MutableCollection 是一个具有写操作的 Collection 接口,例如 add 以及 remove。它的继承者:MutableList/MutableSet
(3)在 Kotlin 中,List 的默认实现是 ArrayList
Map
Map
Map 存储 键-值 对(或 条目);键是唯一的,但是不同的键可以与相同的值配对。
Map 接口提供特定的函数进行通过键访问值、搜索键和值等操作。
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 1)
println("All keys: ${numbersMap.keys}")
println("All values: ${numbersMap.values}")
if ("key2" in numbersMap) println("Value by key \"key2\": ${numbersMap["key2"]}")
if (1 in numbersMap.values) println("The value 1 is in the map")
if (numbersMap.containsValue(1)) println("The value 1 is in the map") // 同上
(1)无论键值对的顺序如何,包含相同键值对的两个 Map 是相等的。
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 1)
val anotherMap = mapOf("key2" to 2, "key1" to 1, "key4" to 1, "key3" to 3)
println("The maps are equal: ${numbersMap == anotherMap}")
(2)MutableMap 是一个具有写操作的 Map 接口,可以使用该接口添加一个新的键值对或更新给定键的值。
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 1)
val anotherMap = mapOf("key2" to 2, "key1" to 1, "key4" to 1, "key3" to 3)
println("The maps are equal: ${numbersMap == anotherMap}")
(3)Map 的默认实现 – LinkedHashMap – 迭代 Map 时保留元素插入的顺序。 反之,另一种实现 – HashMap – 不声明元素的顺序。
迭代:
for(key in hashMap.keys){
println("Element at key $key = ${hashMap[key]}")
}
Set
Set 存储唯一的元素;它们的顺序通常是未定义的。null 元素也是唯一的:一个 Set 只能包含一个 null。当两个 set 具有相同的大小并且对于一个 set 中的每个元素都能在另一个 set 中存在相同元素,则两个 set 相等。
val numbers = setOf(1, 2, 3, 4)
println("Number of elements: ${numbers.size}")
if (numbers.contains(1)) println("1 is in the set")
val numbersBackwards = setOf(4, 3, 2, 1)
println("The sets are equal: ${numbers == numbersBackwards}")
(1)MutableSet 是一个带有来自 MutableCollection 的写操作接口的 Set。
(2)Set的默认实现 - LinkedHashSet – 保留元素插入的顺序。 因此,依赖于顺序的函数,例如 first() 或 last(),会在这些 set 上返回可预测的结果。
val numbers = setOf(1, 2, 3, 4) // LinkedHashSet is the default implementation
val numbersBackwards = setOf(4, 3, 2, 1)
println(numbers.first() == numbersBackwards.first())
println(numbers.first() == numbersBackwards.last())
(3)另一种实现方式 – HashSet – 不声明元素的顺序,所以在它上面调用这些函数会返回不可预测的结果。但是,HashSet 只需要较少的内存来存储相同数量的元素。