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) { …… }
网友评论