1.Null安全
1.1通过代码来理解
var a: String = "abc"
val l = a.length // ok
a = null // compilation error
var b: String? = "abc"
val l = b.length // error: variable 'b' can be null
b = null // ok
1.2安全调用
b?.length
bob?.department?.head?.name
//如果是java需要下面着这样写
if(bob == null) return null;
if(bob.department == null) return null;
if(bob.department.head == null) return null;
return bob.department.head.name;
1.3 ?:操作符
val l: Int = if (b != null) b.length else -1
//和下面一样
val l = b?.length ?: -1
也可以在后面接语句
fun foo(node: Node): String? {
val parent = node.getParent() ?: return null
val name = node.getName() ?: throw IllegalArgumentException("name expected")
// ...
}
1.4 !!操作符
val l = b!!.length //如果b是null,会抛出空指针错误
2.Exceptions
在kotlin,所有的exception类都是继承自Throwable, 和Java基本一致。
try {
// some code
}
catch (e: SomeException) {
// handler
}
finally {
// optional finally block
}
3.Annotations 注释
使用annotation修饰
annotation class Fancy
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class Fancy
annotations可以有带参的构造函数
annotation class Special(val why: String)
@Special("example") class Foo {}
参数类型可以是:
- types that correspond to Java primitive types (Int, Long etc.);
- strings;
- classes (Foo::class);
- enums;
- other annotations;
- arrays of the types listed above.
看下几个例子
annotation class ReplaceWith(val expression: String)
annotation class Deprecated(
val message: String,
val replaceWith: ReplaceWith = ReplaceWith(""))
@Deprecated("This function is deprecated, use === instead", ReplaceWith("this === other"))
import kotlin.reflect.KClass
annotation class Ann(val arg1: KClass<*>, val arg2: KClass<out Any?>)
@Ann(String::class, Int::class) class MyClass
lambdas也可以用annotation修饰
annotation class Suspendable
val f = @Suspendable { Fiber.sleep(10) }
给使用指定位置加上注释,可以给属性或者基础构造函数的参数加上。
class Example(@field:Ann val foo, // annotate Java field
@get:Ann val bar, // annotate Java getter
@param:Ann val quux) // annotate Java constructor parameter
@file:JvmName("Foo")
package org.jetbrains.demo
class Example {
@set:[Inject VisibleForTesting]
var collaborator: Collaborator
}
有下面是支持的
- file
- property (annotations with this target are not visible to Java)
- field
- get (property getter)
- set (property setter)
- receiver (receiver parameter of an extension function or property)
- param (constructor parameter)
- setparam (property setter parameter)
- delegate (the field storing the delegate instance for a delegated property)
另外Java的annotation也可以用在kotlin中。
4.反射
在java平台,需要引入kotlin-reflect.jar来使用反射。
4.1类反射
val c = MyClass::class //是KClass
4.2函数反射
fun isOdd(x: Int) = x % 2 != 0
val numbers = listOf(1, 2, 3)
println(numbers.filter(::isOdd)) // prints [1, 3] //::isOdd等于 (Int) -> Boolean
4.3属性反射
var x = 1
fun main(args: Array<String>) {
println(::x.get()) // prints "1"
::x.set(2)
println(x) // prints "2"
}
4.4和Java反射互用
import kotlin.reflect.jvm.*
class A(val p: Int)
fun main(args: Array<String>) {
println(A::p.javaGetter) // prints "public final int A.getP()"
println(A::p.javaField) // prints "private final int A.p"
}
4.5构造函数反射
class Foo
fun function(factory: () -> Foo) {
val x: Foo = factory()
}
function(::Foo) //::Foo是无参构造函数
5.类型安全的Builders
比较像groovy,可以阅读下面代码
import com.example.html.* // see declarations below
fun result(args: Array<String>) =
html {
head {
title {+"XML encoding with Kotlin"}
}
body {
h1 {+"XML encoding with Kotlin"}
p {+"this format can be used as an alternative markup to XML"}
// an element with attributes and text content
a(href = "http://kotlinlang.org") {+"Kotlin"}
// mixed content
p {
+"This is some"
b {+"mixed"}
+"text. For more see the"
a(href = "http://kotlinlang.org") {+"Kotlin"}
+"project"
}
p {+"some text"}
// content generated by
p {
for (arg in args)
+arg
}
}
}
6.类型别名
使用typealias关键字修饰
typealias NodeSet = Set<Network.Node>
typealias FileTable<K> = MutableMap<K, MutableList<File>>
typealias MyHandler = (Int, String, Any) -> Unit
typealias Predicate<T> = (T) -> Boolean
class A {
inner class Inner
}
class B {
inner class Inner
}
typealias AInner = A.Inner
typealias BInner = B.Inner