Kotlin常用函数以及关键字
1.If语句
fun largerNumber(num1: Int, num2: Int) = if (num1 > num2) num1 else num2
2.When
fun getScore(name: String) = when (name){
"Tom" -> 86
"Jim" -> 77
"Jack" -> 95
"Lily" -> 100
else -> 0
}
3.is关键字就是类型匹配的核心,它相当于J于Java中的instanceof关键字
fun checkNumber(num: Number) {
when (num) {
is Int -> println("number is Int")
is Double -> println("number is Double")
else -> println("number not support")}}
4.for
for (i in 0..10) {println(i)}
///until替代..关键字,你就会发现最后一行10不会再打印出来了。
///downTo降序的区间
for (i in 10 downTo 1) {println(i)}
5.open允许类被继承
class Student : Person() {
var sno = ""
var grade = 0
}
6. init所有主构造函数中的逻辑都可以写在里面
class Student(val sno: String, val grade: Int) : Person() {
init {
println("sno is " + sno)
println("grade is " + grade)}
}
7. constructor 次构造函数
class Student(val sno: String, val grade: Int, name: String, age: Int) :Person(name, age) {
constructor(name: String, age: Int) : this("", 0, name, age) {
}
constructor() : this("", 0) {
}}
8.data数据类 无需实现toString等
data class Cellphone(val brand: String, val price: Double)
fun main() {
val cellphone1 = Cellphone("Samsung", 1299.99)
val cellphone2 = Cellphone("Samsung", 1299.99)
println(cellphone1)
println("cellphone1 equals cellphone2 " + (cellphone1 == cellphone2))
}
9.单例模式
object Singleton {
fun singletonTest() {
println("singletonTest is called.")
}}
10.list
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape")
11. Map
val map = HashMap<String, Int>()
map["Apple"] = 1map["Banana"] = 2map["Orange"] = 3map["Pear"] = 4map["Grape"] = 5
简化val map = mapOf("Apple" to 1, "Banana" to 2, "Orange" to 3, "Pear" to 4, "Grape" to 5)
for ((fruit, number) in map) {
println("fruit is " + fruit + ", number is " + number)
}
12.Lambda
val maxLengthFruit = list.maxBy { fruit -> fruit.length }
13. filter函数
fun main() {
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
val newList = list.filter {
it.length <= 5 }.map {
it.toUpperCase()
}
for (fruit in newList) {
println(fruit)
14. map函数
fun main() {
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
val newList = list.map {
it.toUpperCase()
}
for (fruit in newList) {
println(fruit)
}
}
15. any和all函数
fun main() {
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
val anyResult = list.any {
it.length <= 5
}
val allResult = list.all {
it.length <= 5
}
println("anyResult is " + anyResult + ", allResult is " + allResult)
}
16. Thread
Thread {println("Thread is running")}.start()
17. ?.判空
if (a != null) {
a.doSomething()
}
a?.doSomething()
val c = if (a ! = null) {
a
}
else {
b
}
18. 点击事件
aaa.setOnClickListener({
})
19.?:
val c = if (a ! = null) {a} else {b}
20. let函数
obj.let {
obj2 ->
// 编写具体的业务逻辑
}
fun doStudy(study: Study?) {
study?.let {
it.readBooks()it.doHomework()
}
}
21.!!.
aaa!!.
//!!.的意思是这个参数如果为空,就抛出异常
22.with函数
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape")
val result = with(StringBuilder()) {
append("Start eating fruits.\n")
for (fruit in list) {
append(fruit).append("\n")
}
append("Ate all fruits.")
toString()
}
println(result)
23.run函数
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape")
val result = StringBuilder().run {
append("Start eating fruits.\n")
for (fruit in list) {
append(fruit).append("\n")
}
append("Ate all fruits.")
toString()
}
println(result)
24.apply函数
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape")
val result = StringBuilder().apply {
append("Start eating fruits.\n")
for (fruit in list) {
append(fruit).append("\n")
}
append("Ate all fruits.")
}
println(result.toString())
25.静态方法@JvmStatic
@JvmStatic注解只能加在单例类或companion object中的方法上,如果你尝试加在 一个普通方法上,会直接提示语法错误。
class Util {
fun doAction1() {
println("do action1")
}
companion object {
@JvmStatic
fun doAction2() {
println("do action2")
}
}
}
26.repeat函数
repeat函数是Kotlin中另外一个非常常用的标准函数,它允许你 传入一个数值n,然后会把Lambda表达式中的内容执行n遍。
class MainActivity : AppCompatActivity() {
private val fruitList = ArrayList<Fruit>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initFruits() // 初始化水果数据
val adapter = FruitAdapter(this, R.layout.fruit_item, fruitList)
listView.adapter = adapter
}
private fun initFruits() {
repeat(2) {
fruitList.add(Fruit("Apple", R.drawable.apple_pic))
fruitList.add(Fruit("Banana", R.drawable.banana_pic))
fruitList.add(Fruit("Orange", R.drawable.orange_pic))
fruitList.add(Fruit("Watermelon", R.drawable.watermelon_pic))
fruitList.add(Fruit("Pear", R.drawable.pear_pic))
fruitList.add(Fruit("Grape", R.drawable.grape_pic))
fruitList.add(Fruit("Pineapple", R.drawable.pineapple_pic))
fruitList.add(Fruit("Strawberry", R.drawable.strawberry_pic))
fruitList.add(Fruit("Cherry", R.drawable.cherry_pic))
fruitList.add(Fruit("Mango", R.drawable.mango_pic))
}
}
www.blogss.cn
}
27.lateinit
延时初始化 不用判空
28.密封类
sealed class Result
class Success(val msg: String) : Result()
class Failure(val error: Exception) : Result()
//其他类
fun getResultMsg(result: Result) = when (result) {
is Success -> result.msg
is Failure -> "Error is ${result.error.message}"
}
29.Fragment和Activity之间进行交互,FragmentManager提供了一个类似于 findViewById()的方法,专门用于从布局文件中获取Fragment的实例
val fragment = supportFragmentManager.findFragmentById(R.id.leftFrag) as LeftFragment
//简化
val fragment = leftFrag as LeftFragment
30.Fragment中又该怎样调用Activity 里的方法
if (activity != null) {
val mainActivity = activity as MainActivity
}
31.扩展函数
fun String.lettersCount(): Int {
var count = 0
for (char in this) {
if (char.isLetter()) {
count++
}
}
return count
}
//调用
val count = "ABC123xyz!@#".lettersCount()
32.java中contains,kotlin为 in
//java
if ("hello".contains("he")) {
}
//kotlin
if ("he" in "hello") {
}
33.inner 内部类定义方式
class MainActivity : AppCompatActivity() {
lateinit var timeChangeReceiver: TimeChangeReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intentFilter = IntentFilter()
intentFilter.addAction("android.intent.action.TIME_TICK")
timeChangeReceiver = TimeChangeReceiver()
registerReceiver(timeChangeReceiver, intentFilter)
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(timeChangeReceiver)
}
inner class TimeChangeReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context, "Time has changed", Toast.LENGTH_SHORT).show()
}
}
}
//解开注册
onDestroy()
unregisterReceiver()
34.高阶函数
//kotlin
fun num1AndNum2(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int {
val result = operation(num1, num2)
return result
}
//调用
fun main() {
val num1 = 100
val num2 = 80
val result1 = num1AndNum2(num1, num2) { n1, n2 ->
n1 + n2
}
val result2 = num1AndNum2(num1, num2) { n1, n2 ->
n1 - n2
}
println("result1 is $result1")
println("result2 is $result2")
}
//java代码实现原理
public static int num1AndNum2(int num1, int num2, Function operation) {
int result = (int) operation.invoke(num1, num2);
return result;
}
public static void main() {
int num1 = 100;
int num2 = 80;
int result = num1AndNum2(num1, num2, new Function() {
@Override
public Integer invoke(Integer n1, Integer n2) {
return n1 + n2;
}
});
}
/**考虑到可读性,我对这段代码进行了些许调整,并不是严格对应了Kotlin转换成的Java代码。可
以看到,在这里num1AndNum2()函数的第三个参数变成了一个Function接口,这是一种
Kotlin内置的接口,里面有一个待实现的invoke()函数。而num1AndNum2()函数其实就是调
用了Function接口的invoke()函数,并把num1和num2参数传了进去。
在调用num1AndNum2()函数的时候,之前的Lambda表达式在这里变成了Function接口的匿
名类实现,然后在invoke()函数中实现了n1 + n2的逻辑,并将结果返回。
这就是Kotlin高阶函数背后的实现原理。你会发现,原来我们一直使用的Lambda表达式在底层
被转换成了匿名类的实现方式。这就表明,我们每调用一次Lambda表达式,都会创建一个新
的匿名类实例,当然也会造成额外的内存和性能开销。
为了解决这个问题,Kotlin提供了内联函数的功能,它可以将使用Lambda表达式带来的运行时
开销完全消除。*/
35.内联函数 inline
只需要在定义高阶函数时加上inline关键字的声明即可
inline fun num1AndNum2(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int {
val result = operation(num1, num2)
return result
}
//Kotlin编译器会将Lambda表达式中的代码替换到函数类型参数调用的地方
36.noinline函数
比如,一个高阶函数中如果接收了两个或者更多函数 类型的参数,这时我们给函数加上了inline关键字,那么Kotlin编译器会自动将所有引用的 Lambda表达式全部进行内联。 但是,如果我们只想内联其中的一个Lambda表达式该怎么办呢?这时就可以使用noinline关 键字了
inline fun inlineTest(block1: () -> Unit, noinline block2: () -> Unit) { }
这里使用inline关键字声明了inlineTest()函数,原本block1和block2这两 个函数类型参数所引用的Lambda表达式都会被内联。但是我们在block2参数的前面又加上了 一个noinline关键字,那么现在就只会对block1参数所引用的Lambda表达式进行内联了。 这就是noinline关键字的作用
为什么Kotlin还要提供一个noinline关键字来排除 内联功能呢?这是因为内联的函数类型参数在编译的时候会被进行代码替换,因此它没有真正 的参数属性。非内联的函数类型参数可以自由地传递给其他任何函数,因为它就是一个真实的 参数,而内联的函数类型参数只允许传递给另外一个内联函数,这也是它最大的局限性。
例子:
fun printString(str: String, block: (String) -> Unit) {
println("printString begin")
block(str)
println("printString end")
}
fun main() {
println("main start")
val str = ""
printString(str) { s ->
println("lambda start")
if (s.isEmpty()) return@printString
println(s)
println("lambda end")
}
println("main end")
}
/**这里定义了一个叫作printString()的高阶函数,用于在Lambda表达式中打印传入的字符串
参数。但是如果字符串参数为空,那么就不进行打印。注意,Lambda表达式中是不允许直接
使用return关键字的,这里使用了return@printString的写法,表示进行局部返回,并且
不再执行Lambda表达式的剩余部分代码。*/
但是如果我们将printString()函数声明成一个内联函数,那么情况就不一样了
inline fun printString(str: String, block: (String) -> Unit) {
println("printString begin")
block(str)
println("printString end")
}
fun main() {
println("main start")
val str = ""
printString(str) { s ->
println("lambda start")
if (s.isEmpty()) return
println(s)
println("lambda end")
}
println("main end")
}
38.委托 by函数
例:
class MySet<T>(val helperSet: HashSet<T>) : Set<T> by helperSet {
fun helloWorld() = println("Hello World")
override fun isEmpty() = false
}
这里我们新增了一个helloWorld()方法,并且重写了isEmpty()方法,让它永远返回 false。这当然是一种错误的做法,这里仅仅是为了演示一下而已。现在我们的MySet就成为 了一个全新的数据结构类,它不仅永远不会为空,而且还能打印helloWorld(),至于其他 Set接口中的功能,则和HashSet保持一致。这就是Kotlin的类委托所能实现的功能。
看一下委托属性的语法结构,如下所示:
class MyClass {
var p by Delegate()
}
/**可以看到,这里使用by关键字连接了左边的p属性和右边的Delegate实例,这是什么意思呢?
这种写法就代表着将p属性的具体实现委托给了Delegate类去完成。当调用p属性的时候会自
动调用Delegate类的getValue()方法,当给p属性赋值的时候会自动调用Delegate类的
setValue()方法。
因此,我们还得对Delegate类进行具体的实现才行,代码如下所示:*/
class Delegate {
var propValue: Any? = null
operator fun getValue(myClass: MyClass, prop: KProperty<*>): Any? {
return propValue
}
operator fun setValue(myClass: MyClass, prop: KProperty<*>, value: Any?) {
propValue = value
}
}
39.thread 用法(子线程)
//1、常规
class MyThread : Thread() {
override fun run() {
// 编写具体的逻辑
}
}
MyThread().start()
//2、Runnable写法
class MyThread : Runnable {
override fun run() {
// 编写具体的逻辑
}
}
val myThread = MyThread()
Thread(myThread).start()
//也可以变成
Thread {
// 编写具体的逻辑
}.start()
//3、内置顶层函数
thread {
// 编写具体的逻辑
}
40.AsyncTask
/**在这个DownloadTask中,我们在doInBackground()方法里执行具体的下载任务。这个方法
里的代码都是在子线程中运行的,因而不会影响主线程的运行。注意,这里虚构了一个
doDownload()方法,用于计算当前的下载进度并返回,我们假设这个方法已经存在了。在得
到了当前的下载进度后,下面就该考虑如何把它显示到界面上了,由于doInBackground()方
法是在子线程中运行的,在这里肯定不能进行UI操作,所以我们可以调用
publishProgress()方法并传入当前的下载进度,这样onProgressUpdate()方法就会很
快被调用,在这里就可以进行UI操作了。
当下载完成后,doInBackground()方法会返回一个布尔型变量,这样onPostExecute()方
法就会很快被调用,这个方法也是在主线程中运行的。然后,在这里我们会根据下载的结果弹
出相应的Toast提示,从而完成整个DownloadTask任务。
简单来说,使用AsyncTask的诀窍就是,在doInBackground()方法中执行具体的耗时任务,
在onProgressUpdate()方法中进行UI操作,在onPostExecute()方法中执行一些任务的收
尾工作。*/
class DownloadTask : AsyncTask<Unit, Int, Boolean>() {
override fun onPreExecute() {
progressDialog.show() // 显示进度对话框
}
override fun doInBackground(vararg params: Unit?) = try {
while (true) {
val downloadPercent = doDownload() // 这是一个虚构的方法
publishProgress(downloadPercent)
if (downloadPercent >= 100) {
break
}
}
true
} catch (e: Exception) {
false
}
override fun onProgressUpdate(vararg values: Int?) {
// 在这里更新下载进度
progressDialog.setMessage("Downloaded ${values[0]}%")
}
override fun onPostExecute(result: Boolean) {
progressDialog.dismiss()// 关闭进度对话框
// 在这里提示下载结果
if (result) {
Toast.makeText(context, "Download succeeded", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context, " Download failed", Toast.LENGTH_SHORT).show()
}
}
}
//启动
DownloadTask().execute()