Kotlin浅谈
简介
Kotlin是一门静态语言,支持多种平台,包括移动端、服务端以及浏览器端,此外,Kotlin还是一门融合了面向对象与函数式编程的语言,支持泛型、安全的空判断,并且Kotlin与Java可以做到完全的交互。
Kotlin特点
- 代码量少且代码末尾没有分号。
- 被调用的方法需放到上边。
- Kotlin是空安全的:在编译时期就处理了各种null的情况,避免了执行时异常。
- 它可扩展函数:我们也可以扩展任意类的更多的特性。
- 它也是函数式的:比如,使用lambda表达式来更方便地解决问题。
- 高度互操作性:你可以继续使用所有用Java写的代码和库,甚至可以在一个项目中使用Kotlin和Java两种语言混合编程
As安装插件及添加依赖:
插件安装:File->setting->plugin->Kotlin
依赖添加:Tools ->Kotlin->Configure Kotlin in Project 选定模块后会自动添加依赖
Kotlin的一般属性:
-
作用域:
public:默认,总是可见
internal:同模块可见
protected:类似于private,但对子类也可见
private:声明范围与同模块的子作用域可见,val常量和var变量,默认都是private的 -
三种方法:
扩展方法:Kotlin中的方法可以直接定义在文件中,而不需要依赖于任何的类;
成员方法:写在class或object中的方法;
本地方法: 定义在方法内部的方法,可以访问外部函数的私有成员
关键字:
var:定义变量,默认是private的
val:定义常量,默认是private的
fun:定义方法,默认是public final
Unit:默认方法返回值,类似于Java中的void,可以理解成返回一个没有意义的值
vararg:可变参数
$:字符串模板(取值)
位运算符:or(按位或),and(按位与),shl(有符号左移),shr(有符号右移),
ushr(无符号右移),xor(按位异或),inv(按位取反)
in:在某个范围中
downTo:递减,循环时可用,每次减1
step:步长,循环时可用,设置每次循环的增加或减少的量
when:Kotlin中增强版的switch,可以匹配值,范围,类型与参数
is:判断类型用,类似于Java中的instanceof()
as:设置别名
数据类型
Kotlin中数字相关的内置类型有: byte、short、Int、Long、Float、Double
需要注意的:
1. 没有自动向上转型,比如Int转Long,需要自己调toXxx方法转;
2.Long类型结尾必须为大写的L,不能为小写,比如1024L
3.字符Char不是Number,用单引号来声明,比如'c',不能像Java一样直接拿来当数字使,如果你想把Char的值给Int,需要调toInt()方法
4.Boolean的值为true或false
5.Kotlin不支持8进制,十六进制0x开头,二进制0b开头
6.位运算符,Java中的与或运算符用:|和&,kotlin中使用or和and关键字来替代其他运算符也有分别的关键字替代:shl(有符号左移),shr(有符号右移),ushr(无符号右移),xor(按位异或),inv(按位取反)
数组:
-
数组创建:
定长数组:val fixedSizeArray = arrayOfNulls<Int>(10)
空数组: val empty = emptyArray<Int>()
装箱操作:val arr = arrayOf(1, 2, 3) //还有其他比如IntArrayOf,BooleanArrayOf等
闭包初始化:
val array = Array(10,{num-> num})
for (i in 0..9) print(array[i]) -
数组遍历:
for (i in array) { //元素遍历
print(i)
}for (i in array.indices) { //根据下标遍历
print(array[i])
}
when语句(增强版Switch)
when语句可以匹配类型,值和范围还有参数,而且不用写break语句
例:匹配值与范围
var result = 99
when (result) {
100 -> println("sss")
99 -> println("ss")
in 95..99 -> println("s")
in 90..94 -> println("a")
in 80..89 -> println("A")
else -> println("failed")
}
例:匹配类型(只能匹配变量的类型,或else)
when (result) {
is Int -> println("Int") //暂时测试只有Int类型可以
else -> println("非Int")
}
例:匹配参数
fun doSomeThing(x: Int) = -1 * x //必须要放到使用者上边才能识别
when (result) {
doSomeThing(result) -> println("$result")
else -> println("else:$result") //输出结果:else :99
操作符介绍
-
?:表示当前对象这个对象可能为空,如:
//在变量类型后面加上问号,代表该变量是可空变量 var name: String? = "zhangsan" //如果str不能转为Int类型,则返回null fun parseInt(str: String): Int? { val toInt = str.toInt() return toInt } fun parseInt(str:String)=str.toInt() //缩写方式,因为它能自动推测出返回值类型 b?.length //如果 b非空,就返回 b.length ,否则返回 null,这个表达式的类型是 Int val min = if (2 > 4) { "2da" }else { 9 //可以返回不同类型,但必须有值,或引入Unit类 7 //在if语句块的最后才是最终有效的结果 }
-
!!:表示当前对象不为空的情况下执行
val l: Int = if (b != null) b.length else -1 等价于:val l = b?.length ?: -1 //缩略型定义方法: var i = 9 等价于: var i: Int = 9
-
==号与===号区别
==判断值是否相等;
===判断值及引用是否完全相等; -
: 符号,用于类名后表示继承,用于变量后限定变量类型
-
.. :区间符号
if (i in 1..10) { // 等同于 1 <= i && i <= 10 println(i) } //使用until函数,创建一个不包括其结束元素的区间 for (i in 1 until 10) { //范围[1, 10),不会执行的写法:for (i in 10 until 1) println(i) } for (i in 1..4) print(i) // 输出“1234” for (i in 4..1) print(i) // 注意:这样写什么都不输出 for (i in 4 downTo 1) print(i) // 输出“4321” for (i in 1..4 step 2) print(i) // 输出“13”,注意:step指定了步长为2 for (i in 4 downTo 1 step 2) print(i) // 输出“42” for (str in "didala"){ //kotlin还支持字符串遍历 LogUtils.d(str.toString()) }
-
_(下划线)
data class Book(var id: Int, var name: String) //其中Book声明了id,name两个变量。解构时若只要id一个变量时,可以这么做: val book = Book(1, "英语") val (id, _) = book //提取book中某几项,等价于 id = book.id; Log.d("LogTag", id)
-
::符号
//得到类的Class对象 startActivity(Intent(this@KotlinActivity, MainActivity::class.java)) //内联函数和reified后续介绍 inline fun <reified T> Gson.fromJson(json:String):T { return fromJson(json, T::class.java) } //方法引用 var setBook = setOf<String>("hello", "hi", "你好") //setBook.forEach { print(it)} //it是forEach内部隐藏的参数 setBook.forEach(::print) //var、val在不同场景下,会出现不同方法,如此时的forEach()
-
@限定this符号
class User { inner class State{ fun getUser(): User{ //返回User return this@User } fun getState(): State{ //返回State return this@State } } }
-
@作为标签,跳出循环for或forEach
loop@ for (itemA in arraysA) { var i : Int = 0 for (itemB in arraysB) { i++ if (itemB > 2) { break@loop //注意写法 } println("itemB:$itemB") //$符号在kotlin中才表示引用某个参数,作用类似于java中的%s } }
-
@JvmOverloads方法自动重载
class Overloads { @JvmOverloads fun overloaded(a: Int, b: Int = 0, c: Int = 1){ println("$a, $b, $c") } } //引用时: overloads.overloaded(1, 2, 3); overloads.overloaded(1); overloads.overloaded(1,3);
-
vararg关键字
代表可变参数,只能一个个传值,不能直接使用外部Array,除非使用 ***** 符号表示将Array中所有的元素都当做参数处理fun sum(vararg numbers:Int): Int { var result = 0 for (num in numbers) { result += num } return result } //引用时: val array = intArrayOf(6,7,8,9) sum(1,2,3,4,*array)
-
变量赋值
-
标签法:
fun fun_run(){ //方法赋值最初版,可将run理解为一级函数名(固定不变的),outer为二级函数名 var i: Int = run (outer@{ return@outer 2 }) //简化版 i = run outer@{ return@outer 2 } //精简版 i = run { return@run 1 } println("i:$i") }
- 直接赋值法:
private val inds: String? = "dfsfs"
- if()赋值法:
private val inds2: String? = if (true) { "dfsfs" } else "dfsfs"
- invoke()赋值法(同时也能用于方法的调用执行):
// 一个参数,Unit当于java中的void,表示返回一个没有意义的值 var callback: ((str: String) -> Unit)? = null //此步可理解为在定义类型 callback = { println(it)} //调用invoke()时执行 //因为返回值用的是Unit,所以功能等同于调用方法 callback?.invoke("hello") println("LogTag: ${callback.toString()}") //结果:a.c.a.a<java.lang.String, a.b> //两个参数 var callback2: ((name: String, age: Int) -> Unit)? = null callback2 = { hello: String, world: Int -> println("$hello's age is $world") } //结果:Tom's age is 22 callback2?.invoke("Tom", 22) var callback3 :((num1:Int, num2: Int)->String)? = null //这里定义invoke()后的值是String类型 //类型可以推断 callback3 = { num1, num2 -> var res:Int = num1 + num2 res.toString() //在代码最后,必须对应String类型 } println("LogTagggg: $callback3") //结果: a.c.a.a<java.lang.String, a.b> println("LogTagggg: ${callback3?.invoke(1, 2)}") //结果:3,所以invoke()后的值才是我们需要的结果
-
data关键字,适用于解析类
data class User( var id: Long, var name: String, var url: String, var mbid: String) //这里用是()非{} //相当于: public class User{ public long id; public String name; public String url; public String mbid; } //在kotlin中 data 修饰符 = java中 public + getter + setter + toString + equals + hashCode
-
Bean解析:
inline fun <reified T: Any> Gson.fromJsonNew(json: String): T{ //封装了`Gson.fromJson(String json , Class<T> classOf)`方法 return fromJson(json, T::class.java) } fun main() { val json = "{id:10,url:'url',mbid:'mbid',name:'test'}" var result : Bean = Gson().fromJsonNew(json) println("LogTagggg:"+result.id.toString() + ","+result.name) }
-
扩展方法
可以给任何类添加函数(View,Context等),例如:fun Fragment.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) { Toast.makeText(getActivity(), message, duration).show() } //执行时调用:fragment.toast("Hello world!")
注意:Kotlin 的方法扩展并不是真正修改了对应的类文件,而是在编译器和 IDE 方面做了处理。使我们看起来像是扩展了方法。
AS中java和kotlin 的代码相互转换:
-
java ->kotlin4种方法:
1.ctrl + shift + a 快捷键 输入Convert Java File to Kotlin File
2. ctrl +alt + shift + k 将 Java 代码转换为 Kotlin
3.打开要转换的java文件,然后选择 Code -> Convert Java File to Kotlin File (在最底部)
4.鼠标移到java目录下的任意文件位置,鼠标右键后选new->Kotlin File/class(它默认都会在java目录下创建一个.kt文件),最后将要转换的java代码复制到该.kt文件中即会自动完成转换; -
kotlin ->java:
先Tools>Kotlin>Show Kotlin Bytecode,然后点击Decompile