美文网首页Kotlin编程
Kotlin基本语法

Kotlin基本语法

作者: 卡路fly | 来源:发表于2020-04-03 15:24 被阅读0次

javabean

public class Book {
    private long id;
    private String name;
    
    ...
    getter and setter
    ...
    
}
data class Book(
    val id: Long,
    val name: String) {
        // 构造函数的函数体可以写在init
        init {
            ...
        }
    }
}
data class Forecast(val dtae: Date, val temperature: Float, val details: String)

复制

val f1 = Forecast(Date(), 22.5f, "Cool")
val f2 = f1.copy(temperature = 22f)

映射对象到变量

val f1 = Forecast(Date(), 22.5f, "Cool")
val (date, temperature, details) = f1
会被编译为
val date = f1.component1()
val temperature = = f1.component2()
val details = f1.component3()

别名

import com.animal.dog as puppy  

空安全

// 不能通过编译,不能为空
val not NullBook: Book = null
// 可以为空
val not book: Book? = null
// 不能通过编译,book可能为空
book.print()
// book != null 执行
book?.print()
// 如进行空检查,不需要安全调用操作符调用
if (book != null) {
    book.print()
}
// 确保不为空才会调用,否则抛出异常
book!!.print()
// 使用三元运算符来给定一个是Null时的替代值
val name = book?.name ?: "empty"

习惯用法

// If not null 缩写
val files = File("Test").listFiles()
println(files?.size)

// If not null and else 缩写
val files = File("Test").listFiles()
println(files?.size ?: "empty")

// if null 执行一个语句
val data = ……
val email = data["email"] ?: throw IllegalStateException("Email is missing!")

// if not null 执行代码
val data = ……
data?.let {
    …… // 代码会执行到此处, 假如data不为null
}

// 使用可空布尔
val b: Boolean? = ……
if (b == true) {
    ……
} else {
    // `b` 是 false 或者 null
}

Lambdas

view.setOnClickListener { toast("haha") }

继承

所有类默认不可继承(final),使用open或abstract声明的类可被继承

open class Animal(name: String)
class B(name: String,surname: String) : Animal(name)

函数

使用fun关键字进行定义。当没有指定返回值时,返回Unit,类似void,但Unit是一个真正的对象。
当返回结果可用一个表达式计算出来可以使用等号。

fun add(x: Int,y: Int) : Int = x + y

当函数参数指定为默认值,调用的时候可以不传值进入。

基本类型

  • 数字/字符类型不会自动转型,必须使用明确的类型转换。
val i: Int = 7
val d: Double = i.toDouble()
val c: Char = 'c'
val ii: Int = c.toInt()
  • 位运算,| 使用 or ,& 使用 and
val a = flag1 or flag2
val b = flag1 and flag2
  • 字面可以写明具体类型。
// 没有八进制!!!
val i = 12
val iHex = 0x0f
val l = 3L
val d = 3.5
val f  = 3.5F
  • String可以像数组一样访问被迭代。
val s = "aaa"
val c = s[2]
for (c in s) {
    pring(c)
}

val & var

var: 可变变量

val: 不可变量。实例化之后不能再去改变状态,如果需要一个对象修改之后的版本,会在再创建一个新的对象。编程更加健壮和可预估,是线程安全的,因为不可变,所有线程访问到的对象都是同一个。尽可能地使用val。

Companion objects

使用companion object,里面是静态属性、常量或者函数,就像java中的静态属性或者方法。

When 表达式

when 取代了switch

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> { // 注意这个块
        print("x is neither 1 nor 2")
    }
}

// 多个分支条件放在一起,用逗号分隔:
when (x) {
    0, 1 -> print("x == 0 or x == 1")
    else -> print("otherwise")
}

// 检测一个值在(in)或者不在(!in)一个区间或者集合中:
when (x) {
    in 1..10 -> print("x is in the range")
    in validNumbers -> print("x is valid")
    !in 10..20 -> print("x is outside the range")
    else -> print("none of the above")
}

// 检测一个值是(is)或者不是(!is)一个特定类型的值
fun hasPrefix(x: Any) = when(x) {
    is String -> x.startsWith("prefix")
    else -> false
}

// when 取代 if-else if链。
when {
    x.isOdd() -> print("x is odd")
    x.isEven() -> print("x is even")
    else -> print("x is funny")
}

操作符表

一元操作符
二元操作符 数组操作符 等于操作符

PS: 操作符 === 和 !== 分别是java中的 == 和 != ,并且不能被重载。


函数调用

修饰符

修饰符 描述
public 默认修饰符(当类为private,public成员类也不可见)
private 只能被自己所在文件可见
protected 只能被用在类或接口中的成员上
internal 对整个module可见(当类为private,internal修饰的可见性会限制与它所在的这个类的可见性)

构造器

构造器默认为public,可以修改为private

class C private constructor(a: Int) {...}

单例

class App : Application() {
    companion object {
        var instance: App by DelegatesExt.notNullSingleValue()
    }
    override fun onCreate() {
        super.onCreate()
        instance = this
    }
}

扩展函数

toast("free style")
longToast("free style")

执行一个请求

public class Request(var url: String) {
    public fun run() {
        val str = URL(url).readText()
    }
}

主线程外执行

async() {
    Request(url).run()
    uiThread { longToast("Request performed") }
}

uiThread 可依赖于调用者,如果被一个activity调用,activity.isFinishing()返回TRUE,uiThread不会执行,所以不会在activity销毁时崩溃~
异步调用

async() {
    val res = RequestForecastCommand("1111").execute()
    uiThread {
        forecastList.adapter = ForecastListAdapter(res)
    }
}

内联函数

内联函数:编译时被替换,可以减少内存分配格运行时开销。

(如果一个函数接受一个函数作为它的参数,普通函数内部会创建一个含有那个函数的对象;内联函数会吧我们调用这个函数的地方替换掉,不需要生成一个内部对象。)

  • apply:调用某对象的apply,在函数范围内,可以调用该对象的任意方法并返回该对象,返回当前自己的对象。
  • let:默认当前对象作为闭包的it参数,返回函数内最后一行,或指定return。
  • with:一个单独的函数,返回最后一行,直接调用对象的方法。(let + apply)
  • run:类似apply,返回最后一行。
// 对一个对象实例调用多个方法 (with)
// 这个例子才充分体现了with有没有!!!!之前看到的都什么鬼
class Turtle {
        fun penDown()
        fun penUp()
        fun turn(degrees: Double)
        fun forward(pixels: Double)
}
val myTurtle = Turtle()
with(myTurtle) { // 画一个 100 像素的正方形
        penDown()
        for(i in 1..4) {
            forward(100.0)
            turn(90.0)
        }
        penUp()
}
函数名 定义 参数 返回值 extension 其他
let fun <T, R> T.let(f: (T) -> R): R = f(this) it 闭包返回
apply fun <T> T.apply(f: T.() -> Unit): T { f(); return this } 无(this) this
with fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f() 无(this) 闭包返回 调用方式不同
run fun <T, R> T.run(f: T.() -> R): R = f() 无(this) 闭包返回

区间

区间表达式由具有操作符形式 .. 的 rangeTo 函数辅以 in 和 !in 形成。

for (i in 1..100) { …… }  // 闭区间:包含 100
for (i in 1 until 100) { …… } // 半开区间:不包含 100
for (x in 2..10 step 2) { …… }
for (x in 10 downTo 1) { …… }
if (x in 1..10) { …… }

相关文章

网友评论

    本文标题:Kotlin基本语法

    本文链接:https://www.haomeiwen.com/subject/nmnhphtx.html