Kotlin笔记小结(For Java Developer)
这篇文章为kotlin学习记录,主要针对的是自己的知识盲区,不适用于新手。
文中所有demo均来自于kotlin官网
类型
整形
Type | Size (bits) | Min value | Max value |
---|---|---|---|
Byte | 8 | -128 | 127 |
Short | 16 | -32768 | 32767 |
Int | 32 | -2,147,483,648 (-231) | 2,147,483,647 (231 - 1) |
Long | 64 | -9,223,372,036,854,775,808 (-263) | 9,223,372,036,854,775,807 (263 - 1) |
浮点型
Type | Size (bits) | Significant bits | Exponent bits | Decimal digits |
---|---|---|---|---|
Float | 32 | 24 | 8 | 6-7 |
Double | 64 | 53 | 11 | 15-16 |
变量
只读变量使用val
,可以被重新赋值的变量使用关键字var
// example of valval a: Int = 1 // immediate assignment
val b = 2 // `Int` type is inferred
val c: Int // Type required when no initializer is provided
c = 3 // deferred assignment
// example of var
var x = 5 // `Int` type is inferred
x += 1
函数
默认参数
fun foo(a: Int = 0, b: String = "") { ... }
函数扩展
fun String.spaceToCamelCase() { ... }"Convert this to camelcase".spaceToCamelCase()
单行表达式函数
fun theAnswer() = 42// 同样适用于when
fun transform(color: String): Int = when (color) {
"Red" -> 0
"Green" -> 1
"Blue" -> 2
else -> throw IllegalArgumentException("Invalid color param value")
}
Lambda表达式
匿名函数
带receiver的函数字面量
类似于函数扩展,使得你能够直接在函数体中直接返回到receiver object
. 在函数体重,receiver object使用this
访问到,你可以通过this
来获取到reciver object中的属性和方法。
val sum: Int.(Int) -> Int = { other -> plus(other)// 匿名函数
val sum = fun Int.(other: Int): Int = this + other
Lambda表达式
基本语法
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
- lambda 使用
{}
包围 - 在
→
后面的为函数体 - 如果lambda的返回值不为空(
Unit
),那么最后一个表达式即为返回值,上面的例子中,x + y
即为返回值
类型声明可以省略,简略写法为:
val sum = { x: Int, y: Int -> x + y }
lambda为函数的最后一个参数
如果lambda为函数的最后一个参数,那么可以直接简写在函数外面,例如
val product = items.fold(1) { acc, e -> acc * e }// 如果lambda作为函数的最后一个参数,那么,函数()可以省略
run { println("...") }
隐式的it
如果lambda只有一个参数,那么这个参数可以不必要声明,参数会隐式被it
代替
ints.filter { it > 0 } // this literal is of type '(it: Int) -> Boolean'// 等价于
ints.filter { intVal -> intVal > 0 }
lambda返回值
默认如果lambda的返回值不为空(Unit
),那么最后一个表达式即为返回值,但是也可以显示地使用return来进行值的返回,但是要遵循qualified return语法
ints.filter { val shouldFilter = it > 0
shouldFilter
}
ints.filter {
val shouldFilter = it > 0
return@filter shouldFilter
}
跳过lambda的返回值
如果不需要使用到lambda的参数,那么可以使用_
代替
map.forEach { _, value -> println("$value!") }
匿名函数
匿名函数和lambda表达式一样,都是函数字面量。
Function literals are functions that are not declared but are passed immediately as an expression.
fun(x: Int, y: Int): Int = x + y
和lambda相比,匿名函数主要有两点不同
- 匿名函数可以指定返回类型,而lambda不同
- 如果没有定义返回标签,lambda的返回会直接返回到最近定义了
fun
关键字的函数,而匿名函数会返回到函数本身
类
类的继承使用:
,类默认是final
类型的(即不可修改),如果要让类可继承,使用open
关键字
open class Shapeclass Rectangle(var height: Double, var length: Double): Shape() {
var perimeter = (height + length) * 2
}
DTOs(POJOs/POCOs)
data class主要用作承载数据的对象,可以用作两个系统之间数据的交换
data class Customer(val name: String, val email: String)
- getters (and setters in case of
var
s) for all properties - equals()
- hashCode()
- toString()
- copy()
- component1(), component2() 用作数据解构
实例化一个抽象类
abstract class MyAbstractClass { abstract fun doSomething()
abstract fun sleep()
}
fun main() {
val myObject = object : MyAbstractClass() {
override fun doSomething() {
// ...
}
override fun sleep() { // ...
}
}
myObject.doSomething()
}
匿名类
Object表达式
主要用来创建匿名类
val helloWorld = object { val hello = "Hello"
val world = "World"
// object expressions extend Any, so `override` is required on `toString()`
override fun toString() = "$hello $world"
}
匿名内部类
匿名内部类也叫伴生类,使用关键字companion
,通常的作用是为类提供静态属性和方法,类似于java的static
关键字
// 一个类中只允许声明一个伴生类// 下面的例子中,如果同时存在两个伴生类,会报类型错误
class MyClass {
// 也可以声明名字
companion object Factory {
fun create(): MyClass = MyClass()
}
// 匿名, Companion
companion object {
fun create(): MyClass = MyClass()
}
}
fun main() {
// 调用可以省略掉伴生类名
println(MyClass.create())
println(MyClass.Factory.create())
println(MyClass.Companion.create())
}
字符串模板
var a = 1// simple name in template:
val s1 = "a is $a"
a = 2
// 如果需要计算,则使用${xxx}来表示
// arbitrary expression in template:
val s2 = "${s1.replace("is", "was")}, but now is $a"
条件判断
条件判断采用关键字if / else if / else
,需要注意一点的是if
也可以作为表达式使用
fun maxOf(a: Int, b: Int) = if (a > b) a else b
if-not-null-else 简写
val files = File("Test").listFiles()println(files?.size ?: "empty") // if files is null, this prints "empty"
// To calculate the fallback value in a code block, use `run`
val filesSize = files?.size ?: run {
return someSize
}
println(filesSize)
if not null 执行 (let)
val value = ...value?.let {
... // execute this block if not null
}
Break and continue 标签
loop@ for (i in 1..100) { for (j in 1..100) {
if (...) break@loop
}
}
Return to 自定义标签
the
return
-expression returns from the nearest enclosing function
fun foo() { listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return // non-local return directly to the caller of foo()
print(it)
}
println("this point is unreachable")
}
// To return from a lambda expression, label it and qualify the return:
fun foo() {
listOf(1, 2, 3, 4, 5).forEach lit@{
if (it == 3) return@lit // local return to the caller of the lambda - the forEach loop
print(it)
}
print(" done with explicit label")
}
// Often it is more convenient to use implicit labels
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@forEach // local return to the caller of the lambda - the forEach loop
print(it)
}
print(" done with implicit label")
}
// Return to anonymous function
fun foo() {
listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) {
if (value == 3) return // local return to the caller of the anonymous function - the forEach loop
print(value)
})
print(" done with anonymous function")
}
When(更强大的Switch)
fun describe(obj: Any): String = when (obj) {
1 -> "One"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "Not a string"
else -> "Unknown"
}
Ranges
使用in
关键字来判断一个变量是否处在这个区间中
val x = 10val y = 9
if (x in 1..y+1) {
println("fits in range")
}
类型检查和自动转换
fun getStringLength(obj: Any): Int? { if (obj is String) {
// `obj` is automatically cast to `String` in this branch
return obj.length
}
// `obj` is still of type `Any` outside of the type-checked branch
return null
}
// 或者
fun getStringLength(obj: Any): Int? {
if (obj !is String) return null
// `obj` is automatically cast to `String` in this branch
return obj.length
}
不安全转换
val x: String = y as String
安全转换
val x: String? = y as? String
代理
代理使用关键字by
,代表的是将原本应该自己职责代理给其他的类或者属性
类代理
interface Base { fun printMessage()
fun printMessageLine()
}
class BaseImpl(val x: Int) : Base {
override fun printMessage() { print(x) }
override fun printMessageLine() { println(x) }
}
// 交给代理类Base去做
class Derived(b: Base) : Base by b {
// 也可以重新override
override fun printMessage() { print("abc") }
}
fun main() {
val b = BaseImpl(10)
Derived(b).printMessage()
Derived(b).printMessageLine()
}
属性代理
一个规划化的栗子
以上是 Kotlin笔记小结(For Java Developer) 的全部内容, 来源链接: utcz.com/z/394930.html