Kotlin 与 Java 的关系 Java运行过程:Java源代码 -> 编译 -> 生成class文件 -> JVM解释执行
Java虚拟机并不关心class文件是如何生成的,因此也可以使用Kotlin生成class文件,JVM也可以解释执行。
Kotlin可以无缝使用Java第三方的开源库。
Q:Android为什么推荐Kotlin?Kotlin与Java比有哪些优势?
A:
空安全
Lambda表达式和高阶函数
Kotlin更简洁,引入了数据类、get、set方法等
拓展函数
支持协程
完全兼容Java
val 与 var 类比JavaScript中的const
和let
。
val
用于声明常量,相当于加了final
,赋值后无法修改;var
用于声明变量。
Any、Unit
Any
等同于Java中的Object
,是所有类的父类
Unit
等同于void
,当函数无返回值时会自动加上返回值Unit
if Kotlin中的if
是带有返回值的,返回值即花括号内的最后一行表达式的值:
1 2 3 4 5 val max = if (a > b) { a } else { b }
字符串 字符串模板 $
后花括号内可以是一个表达式:
1 2 val str = "你好" println("$str ,${str.replace("你好" , "再见" )} !" )
多行字符串 三对双引号内的字符串可换行:
1 2 3 4 5 6 7 8 val poem = """ 关关雎鸠, 在河之洲。 窈窕淑女, 君子好逑。 """ .trimIndent()println(poem)
其中trimIndent
函数的作用是去除输入行的公共最小缩进(空行不影响)。输出为
1 2 3 4 关关雎鸠, 在河之洲。 窈窕淑女, 君子好逑。
有时为了让代码更清晰,我们可以使用|
符号结合trimMargin
函数来标记实际字符串的开始位置:
1 2 3 4 5 6 7 8 val poem = """ | 蒹葭苍苍, |白露为霜。 | 所谓伊人, |在水一方。 """ .trimMargin()println(poem)
其中trimMargin
函数的作用是将多行字符串中的每行内容使用特定的前导字符(默认为|
)进行标记,然后去除这些字符及其前面的空白。输出为
1 2 3 4 蒹葭苍苍, 白露为霜。 所谓伊人, 在水一方。
也可指定不同的前导字符:
1 2 3 4 5 6 7 8 val poem = """ >郎骑竹马来, > 绕床弄青梅。 >同居长干里, > 两小无嫌猜。 """ .trimMargin(">" )println(poem)
when 相当于switch
,不过用起来更方便。
1 2 3 4 5 6 7 fun getScore (name: String ) = when (name) { "张三" -> 85 "李四" -> { return 91 } else -> 0 }
区间 闭区间
左闭右开区间
降序闭区间
循环 for - in 循环 1 2 3 4 5 6 7 8 9 10 for (i in 0 until 10 ) { println(i) } for (i in 0. .10 step 2 ) { println(i) }
构造函数 Kotlin中有主次构造函数之分。
主构造函数没有函数体,直接定义在类名的后面。若想在主构造函数中编写一些逻辑,将代码写在init
中:
1 2 3 4 5 6 7 class Student (val name, val grade) { init { } } Student('张三' , 86 )
次构造函数有函数体,且必须调用主构造函数。
1 2 3 4 5 6 7 8 9 10 11 class Student (val name, val grade) { init { } constructor (name: String) : this (name, 0 ) { } } Student('张三' , 86 )
继承 Kotlin中非抽象类默认都是不可以被继承的,相当于给类加上了final
。要声明为可继承类,需要加上open
关键字。
同时子类中的构造函数必须调用父类中的构造函数。
1 2 3 4 5 6 7 8 9 10 11 open class Person (val name) { } class Student (val name, val grade) : Person(name) { init { } } Student('张三' , 86 )
接口 1 2 3 4 5 6 7 8 9 10 interface Rectangle { fun getPerimeter () fun getArea () } class Square (edge: Double ) : Shape(), Rectangle { override fun getPerimeter () = edge * 4 override fun getArea () = edge * edge }
单例 Java中实现单例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Singleton { private static Singleton instance; private Singleton () {} public synchronized static Singleton getInstance () { if (instance == null ) { instance = new Singleton (); } return instance; } public void singletonTest () { System.out.println("singletonTest方法被调用" ); } } Singleton singleton = Singleton.getInstance();singleton.singletonTest();
Kotlin中实现单例十分简便,只需要将关键字class
改为object
即可:
1 2 3 4 5 6 7 object Singleton { fun singletonTest () { println("singletonTest is called." ) } } Singleton.singletonTest()
拓展函数 我们可以为某一个数据类型添加自定义的方法。
举个例子,如对时间进行格式化,一种普通做法是写一个工具类,用伴生对象实现类似静态方法的效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class DateTimeUtil { companion object { private const val DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss" fun format (dateTime: LocalDateTime ) : String { val formatter = DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT) return formatter.format(dateTime) } } } fun main () { val dateTime = LocalDateTime.now() println("$dateTime " ) val formattedDateTime = DateTimeUtil.format(dateTime) println("$formattedDateTime " ) }
除此之外还有另一种更为优雅的方法:
1 2 3 4 5 6 7 8 9 10 11 fun LocalDateTime.format () : String { val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss" ) return formatter.format(this ) } fun main () { val dateTime = LocalDateTime.now() println("$dateTime " ) println(dateTime.format()) }
这里调用的format
函数是我们自定义的。
kotlin与dart都有这种特性。
可见性
List、Set、Map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 val list = listOf("春秋左氏传" , "春秋公羊传" , "春秋谷梁传" ) val mutableList = mutableListOf("诗经" , "尚书" , "礼记" , "易经" ) mutableList.add("春秋" ) val set = setOf("白起" , "王翦" , "廉颇" , "李牧" )val mutableSet = mutableSetOf("齐桓公" , "晋文公" , "秦穆公" , "宋襄公" )mutableSet.add("楚庄王" ) val map = mapOf("儒" to "孔子" , "法" to "韩非子" , "墨" to "墨子" , "道" to "庄子" )val mutableMap = mutableMapOf("齐" to "临淄" , "楚" to "郢都" , "燕" to "蓟城" , "韩" to "新郑" , "赵" to "邯郸" , "魏" to "大梁" )mutableList.add("秦" to "咸阳" )
Lambda表达式 即可当做参数传递的一段代码。
完整结构:val lambda = { param1: Type, param2: Type -> 函数体 }
,最后一行表达式的值作为整个Lambda表达式的返回值。
1 2 3 4 5 6 7 8 9 10 button.setOnClickListener({ data -> println(data ) }) button.setOnClickListener() { data -> println(data ) } button.setOnClickListener { data -> println(data ) } button.setOnClickListener { println(it) }
参观我的个人网站:http://saoke.fun