基本语法

val value: String? = "HelloWorld"
val name: String = getName() ?: return //如果是null就return
println("$arg1 + $arg2 = ${arg1 + arg2}") //字符串模板
val FINAL_HELLO_CHINA = "HelloChina" //类型可以不写,自动推导
val args1 = arrayOf(1,2,3)
val range: IntRange = 0..1024 // [0, 1024]
val range_exclusive: IntRange = 0 until 1024 // [0, 1024) = [0, 1023] class A {
var b = 0
lateinit var c: String //var延迟初始化用lateinit,使用 lateinit 关键字,变量在定义时不需要初始化,所以在使用questionTextView变量时,不需要加上 ? 和 !! 操作符。在使用第一次变量之前,一定要保证为questionTextView赋值 , 不然会出现空指针异常。
lateinit var d: X
val e: X by lazy {
//val延迟初始化用lazy代理
println("init X")
X()
} //第一次调用 get() 会执行已传递给 lazy() 的 lambda 表达式并记录结果, 后续调用 get() 只是返回记录的结果。
private val linearLayoutManager by lazy {
LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
} var cc: String? = null //初始化成null不好
}
abstract class Person(open val age: Int) {
//只有open的成员和类才能被继承,接口和抽象类默认是open的
abstract fun work()
} //没有三目运算符,可以使用if 表达式
val max = if (a > b) a else b //对于bean对象可以这样写
data class Forecast(val date: Date, val temperature: Float, val details: String) //Kotlin 的构造函数可以写在类头中,跟在类名后面
class Person( var name:String){ private var description: String? = null //在主构造函数中不能有任何代码实现,如果有额外的代码需要在构造方法中执行,你需要放到init代码块中执行
init {
name = "Zhang Tao"
} internal fun sayHello() {
println("hello $name")
} fun printName(){
println(name)
} //这里我们让次级构造函数调用了主构造函数,完成 name 的赋值。
// 由于次级构造函数不能直接将参数转换为字段,所以需要手动声明一个 description 字段,并为 description 字段赋值。
constructor(name: String, description: String) : this(name) {
this.description = description
} } class Latitude private constructor(val value: Double) {
companion object {//伴随对象
//加上这个注解Java可以直接像静态那样调用,否则得Latitude.companion.ofDouble(3.0)
@JvmStatic
fun ofDouble(double: Double): Latitude {
return Latitude(double)
} fun ofLatitude(latitude: Latitude): Latitude {
return Latitude(latitude.value)
} @JvmField
val TAG: String = "Latitude"
}
} class Manager : Driver, Writer {
override fun write() { } override fun drive() { }
} //扩展方法,不用运算符operator的话,用"abc".times(16)这样来调用,jva可以类名.times("abc", 16)调用
operator fun String.times(int: Int): String {
val stringBuilder = StringBuilder()
for (i in 0 until int) {
stringBuilder.append(this)
}
return stringBuilder.toString()
} //函数引用
val pdfPrinter = PdfPrinter()
args.forEach(pdfPrinter::println) class PdfPrinter {
fun println(any: Any) {
kotlin.io.println(any) //重名了可以用包名调用
}
} //常见的高阶函数
val list = listOf<Int>(1, 2, 3, 5, 10, 8, 2)
val newList = ArrayList<Int>();
list.forEach {
val newElement = it * 2 + 3
newList.add(newElement)
}
//和上面一样,上面麻烦,map可以对集合进行操作,返回一个修改过得集合
//flatmap,对集合的集合进行操作,省去了俩次遍历的麻烦
val newList2 = list.map { it * 2 + 3 }
val newList3 = list.map { Int::toDouble }
newList3.forEach(::println)
newList3.map(::println) //和上面输出一样,但是又重新add了一个集合,不好,纯粹用于迭代的话会影响性能,实现里面还有一个数组 //提取开头指定数量或符合指定条件的子集
list.takeWhile { it <= 3 }.forEach(::println) //小于的去掉
list.forEach {
if (it % 2 == 0) {
println(it)
}
}
list.filter { it.isEvent() }.forEach(::println)//过滤 val person = findPerson();
//person是可null的,所以需要?
println(person?.age)
println(person?.name)
//上面太麻烦,findPerson加了?,所以后面不需要了,减少的判空操作。let可以安全调用
findPerson()?.let { person ->
person.work()
println(person.age)
}
//还可以更简洁,person也不用写
findPerson()?.apply {
work()
println(age)
}
//使用apply做对象的初始化
return TextView(context).apply {
text = "test"
setOnClickListener(onClickListener)
} //use不用close了
BufferedReader(FileReader("hello.txt")).use {
var line: String?
while (true) {
//it表示当前对象BufferedReader,所以可以用它的方法
line = it.readLine() ?: break
println(line)
}
}

使用技巧

take是从集合中取前几个元素

takeLast是从集合中取后几个元素

sortedBy 排序

过滤list,符合过滤条件的就是过滤结果

filterNot把符合条件的过滤掉,剩下的是结果。这个操作和 filter 相反

slice,取集合中的某一部分

val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.slice(1..3))
println(numbers.slice(0..4 step 2))
println(numbers.slice(setOf(3, 5, 0))) [two, three, four]
[one, three, five]
[four, six, one] val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.takeWhile { !it.startsWith('f') })
println(numbers.takeLastWhile { it != "three" })
println(numbers.dropWhile { it.length == 3 })
println(numbers.dropLastWhile { it.contains('i') }) [one, two, three]
[four, five, six]
[three, four, five, six]
[one, two, three, four]
  • 扩展函数(类似于工具类)
   fun toast(message: String, length: Int = Toast.LENGTH_SHORT) {
Toast.makeText(this, message, length).show()
} toast("hello") //扩展函数,我们就可以在每一个Activity中直接使用toast()函数了。
fun Context.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(this, message, duration).show()
}

!! 强⾏行行调⽤用符

?. 安全调⽤用符

  • kotlin默认不能空,变量类型后面跟?号定义,表明这是一个可空类型
  • ?. 代表着如果该类型为空的话就返回null不做后续的操作,如果不为空的话才会去访问对应的方法或者属性
  • !!. 代表着如果该类型为空的话就抛出NullPointerException,如果不为空就去访问对应的方法或者属性, 所以只有在很少的特定场景才用这种符号,代表着程序不处理这种异常的case了,会像java代码一样抛出NullPointerException。 而且代码中一定不用出现下面这种代码,会让代码可读性很差而且如果有空指针异常,我们也不能马上发现是哪空了:
  /*
* 不推荐这样的写法:链式的连续用!!.
* */
val user = User()
user!!.name!!.subSequence(0,5)!!.length

在 Kotlin 中创建单例不用像 Java 中那么复杂,只需要把 class 换成 object 就可以了。

object Sample {    val name = "A name"}

//饿汉式的单例,并且实现了线程安全
object A {
val number: Int = 1 、
fun method() {
println("A.method()")
}
}

companion 可以理解为伴随、伴生,表示修饰的对象和外部类绑定。类似静态变量

写在顶级的函数(不需要在class里写方法)或者变量有个好处:在 Android Studio 中写代码时,IDE 很容易根据你写的函数前几个字母自动联想出相应的函数。这样提高了写代码的效率,而且可以减少项目中的重复代码。

如果想写工具类的功能,直接创建文件,写 top-level「顶层」函数。

创建数组,增加很多有用的工具函数

contains()first()find()

val strs: Array<String> = arrayOf("a", "b", "c")

循环通过标准函数 repeat()

repeat(100) {
// todo
}

map也可以这样创建

val map = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 3)

listOf() 创建不可变的 List,mutableListOf() 创建可变的 List

Kotlin 中集合分为两种类型:只读的和可变的。这里的只读有两层意思:

集合的 size 不可变

集合中的元素值不可变

可以转换

map.toMutableMap()

构造器

class User constructor(var name: String) {                                   // 直接调用主构造器
constructor(name: String, id: Int) : this(name) { } // 通过上一个次构造器,间接调用主构造器
constructor(name: String, id: Int, age: Int) : this(name, id) { }
}

forEach:遍历每一个元素

filter:对每个元素进行过滤操作,如果 lambda 表达式中的条件成立则留下该元素,否则剔除,最终生成新的集合

map:遍历每个元素并执行给定表达式,最终形成新的集合

flatMap:遍历每个元素,并为每个元素创建新的集合,最后合并到一个集合中

Elvis 操作符

通过 ?: 的操作来简化 if null 的操作

fun validate(user: User) {
val id = user.id ?: return
// 验证 user.id 是否为空,为空时 return
}
// 等同于
fun validate(user: User) {
if (user.id == null) {
return
}
val id = user.id
}

== :可以对基本数据类型以及 String 等类型进行内容比较,相当于 Java 中的 equals

=== :对引用的内存地址进行比较,相当于 Java 中的 ==

如果每个类型都去实现诸如 TextViewList、ActivityList 这样的具体的类型,显然是不可能的。因此就诞生了「泛型」,它的意思是把具体的类型泛化,编码的时候用符号来指代类型,在使用的时候,再确定它的类型

使用关键字 out 来支持协变,等同于 Java 中的上界通配符 ? extends。

使用关键字 in 来支持逆变,等同于 Java 中的下界通配符 ? super。

var textViews: List<out TextView>
var textViews: List<in TextView>

Kotlin 标准函数

使⽤用时可以通过简单的规则作出一些判断

  • 返回⾃自身

    从 apply 和 also 中选

    作⽤域中使⽤ this 作为参数选择 apply

    作⽤域中使⽤ it 作为参数选择 also
  • 不需要返回⾃自身

    从 run 和 let 中选择

    作用域中使用 this 作为参数,选择 run

    作用域中使用 it 作为参数,选择 let

apply 适合对一个对象做附加操作的时候

let 适合配合空判断的时候

with 适合对同一个对象进行多次操作的时候

协程就是kotlin官方提供的线程api

属性委托

有些常见的属性操作,我们可以通过委托方式,让它实现,例如:lazy 延迟属性: 值只在第一次访问的时候计算

类委托

可以通过类委托来减少 extend类委托的时,编译器回优使用自身重新函数,而不是委托对象的函数

interface Base{
fun print()
} case BaseImpl(var x: Int):Base{ override fun print(){
print(x)
} }
// Derived 的 print 实现会通过构造函数的b对象来完成class Derived(b: base): Base by b

委托就是代理

  //接口代理,可以不是必须实现接口或抽象类的方法
class SeniorManager(val driver: Driver, val writer: Writer) : Driver by driver, Writer by writer class CarDriver : Driver {
override fun drive() {
println("开车呢")
}
} class PPTWriter : Writer {
override fun write() {
println("做PPT呢")
} } interface Driver {
fun drive()
} interface Writer {
fun write()
} val driver = CarDriver()
val writer = PPTWriter()
val seniorManager = SeniorManager(driver, writer)
seniorManager.drive()
seniorManager.write() //类委托
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}
class Derived(b: Base) : Base by b//实现继承的代替方式
fun main(args: Array<String>) {
val b = BaseImpl(10)
Derived(b).print() // prints 10
}

使用 类名::class 获取的是 Kotlin 的类型是 KClass

使用 类名::class.java 获取的是 Java 的类型

Any

Kotlin 的顶层父类是 Any ,对应 Java 当中的 Object ,但是比 Object 少了 wait()/notify()等函数

Unit

Kotlin 中的 Unit 对应 Java 中的 void

在 Java 中通过 「类名.this」 获取目标类引用

在 Kotlin 中通过「this@类名」获取目标类引用

Kotlin基本语法和使用技巧的更多相关文章

  1. Kotlin 特性 语法糖 优势 扩展 高阶 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  2. Kotlin基本语法和使用

    Kotlin 是一个基于 JVM 的新的编程语言,由 JetBrains 开发.与Java相比,Kotlin的语法更简洁.更具表达性,而且提供了更多的特性. Kotlin是使用Java开发者的思维被创 ...

  3. Kotlin基础语法学习

    Kotline简介 Kotlin是一门与Swift类似的静态类型JVM语言,由JetBrains设计开发并开源.与Java相比,Kotlin的语法更简洁.更具表达性,而且提供了更多的特性,比如,高阶函 ...

  4. JavaScript中if语句优化和部分语法糖小技巧推荐

    前言 在前端日常开发过程中,if else判断语句使用的次数应该是比较频繁的了,一些较为复杂的场景,可能会用到很多判断,在某个代码块使用很多if else时,代码会显得较为冗余,阅读起来不够清晰. 除 ...

  5. Kotlin基本语法笔记之函数、变量的定义及null检测

    定义函数 fun sum(a: Int, b: Int): Int { return a + b } 该函数中两个参数的类型都是Int,返回类型是Int 也可以做如下简化 fun sum(a: Int ...

  6. Kotlin 基础语法

    Kotlin 文件以 .kt 为后缀. 包声明 代码文件的开头一般为包的声明: package com.runoob.main import java.util.* fun test() {} cla ...

  7. Kotlin 基本语法

    常量 val a: Int = 5 变量 var a: Int = 5 Any:匹配任何类型 ?:nullable,比如 a?.toString,如果 a 为 null 不会出错. 函数基本结构 fu ...

  8. Kotlin基本语法笔记3之定义类、继承及创建实例

    定义类 class MyObject private constructor(name: String, age: Int) { private var name: String private va ...

  9. Kotlin基础语法:变量、函数、类、枚举、控制流

    一切都需要从基础学起! 前言: 在Kotlin语言中,没有分号的概念了,也就是每一行代码,都不在需要用分号结束了 点击查看代码 定义 常量:val --相当于java当中的final 变量:var 关 ...

随机推荐

  1. 洛谷P1169 [ZJOI2007]棋盘制作 悬线法 动态规划

    P1169 [ZJOI2007]棋盘制作 (逼着自己做DP 题意: 给定一个包含0,1的矩阵,求出一个面积最大的正方形矩阵和长方形矩阵,要求矩阵中相邻两个的值不同. 思路: 悬线法. 用途: 解决给定 ...

  2. 洛谷-P1414 又是毕业季II -枚举因子

    P1414 又是毕业季II:https://www.luogu.org/problemnew/show/P1414 题意: 给定一个长度为n的数列.要求输出n个数字,每个数字代表从给定数列中最合理地取 ...

  3. BZOJ2152 聪聪可可 (点分治)

    2152: 聪聪可可 题意: 在一棵边带权的树中,问任取两个点,这两个点间的权值和是3的倍数的概率. 思路: 经典的点分治题目. 利用点分治在计算所有路径长度,把路径长度对3取模,用t[0],t[1] ...

  4. CF - 1108 E 枚举上界+线段树维护

    题目传送门 枚举每个点作为最大值的那个点.然后既然是作为最大值出现的话,那么这个点就是不需要被减去的,因为如果最小值也在这个区间内的话,2者都减去1,对答案没有影响,如果是最小值不出现在这个区间内的话 ...

  5. Mac 不显示未知来源选项的解决办法/连接不上网络

    原文来自百度经验: http://jingyan.baidu.com/article/eae078278b37d41fec5485b2.html 灰常感谢原作 关于mac无法连接wifi,我的解决办法 ...

  6. 深入理解 ThreadLocal

    前言 上篇文章 深入理解 Handler 消息机制 中提到了获取线程的 Looper 是通过 ThreadLocal 来实现的: public static @Nullable Looper myLo ...

  7. asp.net core 使用 NLog日志

    NLog是一个配置灵活的日志记录类库,拥有输出日志到文件.存储入库.发送到udp地址的高级功能 1 添加 nlog nuget包 Nlog和NLog.Web.AspNetCore 安装完成后   2 ...

  8. JavaScript中的this到底是怎样的?

    this是困惑JavaScript开发者的一大‘毒瘤’,在开发过程中,但凡用到this的时候,我们都会很头疼,那么这个this在JavaScript中到底是怎么样的?身为一个前端coder,这是一个避 ...

  9. Jmeter安装图文及入门教程

    一.JMeter介绍 JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域.它可以用于测试静态和动态资源,例如 ...

  10. Linux 笔记 - 第十一章 正则表达式

    博客地址:http://www.moonxy.com 一.前言 正则表达式(英语为 Regular Expression,在代码中常简写为 regex.regexp 或 RE),是使用单个字符串来描述 ...