1.字符串的截取
fun main(args: Array<String>) {
val text = """
|多行字符串
|多行字符串
""".trimMargin()//使用该函数去除前置空格时需要有边界前缀,边界前缀不打印.直接使用.trim()会只有去除第一行的空格
println(text) // 输出有一些前置空格,
}
fun main(args: Array<String>) {
val price = """
${'$'}9.99
"""
println(price) // 求值结果为 $9.99
}
3. vararg 关键字可变参数
fun vars(vararg v:Int){
for(vt in v){
print(vt)
}
}
// 测试
fun main(args: Array<String>) {
vars(1,2,3,4,5) // 输出12345
}
4. lambda关键字 (匿名函数)
// 测试
fun main(args: Array<String>) {
val sumLambda: (Int, Int) -> Int = {x,y -> x+y}
println(sumLambda(1,2)) // 输出 3
}
5. NULL 处理
//类型后面加?表示可为空
var age: String? = "23"
//抛出空指针异常
val ages = age!!.toInt()
//不做处理返回 null
val ages1 = age?.toInt()
//age为空返回-1
val ages2 = age?.toInt() ?: -1
6. 遍历数组
fun main(args: Array<String>) {
val items = listOf("apple", "banana", "kiwi")
for (item in items) {
println(item)
}
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
}
输出结果:
apple
banana
kiwi
item at 0 is apple
item at 1 is banana
item at 2 is kiwi
7. for 循环的跳步执行及翻转
fun main(args: Array<String>) {
for (i in 1..4) print(i) //1234
println()
for (i in 4 downTo 1) print(i) //4321
println()
for (i in 1..4 step 2) print(i) //13
println()
for (i in 4 downTo 1 step 2) print(i)//42
println()
for (i in 1 until 10) { // i in [1, 10), 不包含 10
print(i) //123456789
}
}
8. lable的使用
1.给内侧for-break 添加标签只能打印20~25的数字,只能跳出内侧循环
(可以说这里添加标签相当于没有添加标签,因为break关键字本身就是要跳出所在的循环圈)
fun main(args: Array<String>) {
for (i in 1..10) {
loop@ for (index in 20..30){
print("$index,")
if (index ==25)break@loop
}
print("*$i*")
}
}
截图有限,结果是循环了10次
给外侧for-break添加标签可以跳出外侧循环
fun main(args: Array<String>) {
loop@ for (i in 1..5) {
for (index in 20..30){
print("$index,")
if (index ==25)break@loop
}
print("*$i*")
}
}
只打印一次20~25
3.给return 添加标签,不添加下面的标签时将结束整个函数,即end不打印
fun main(args: Array<String>){
val indexes = arrayOf(1, 2, 3, 4, 5, 6, 7)
//forEach是内联函数
indexes.forEach loop@ {
if (it > 5) {
return@loop
}
println(it)
}
println("End")
}
4.注意if语句的条件判断,==return会跳过这次循环,>号是永久性的跳出(与3对比看)
fun returnDemo2(){
println("START : "+::returnDemo2.name)
val intArray = intArrayOf(1,2,3,4,5,6,7)
intArray.forEach here@{
if (it == 3) return@here//指令跳转到lambda表达式标签here@处。
println(it) //继续下一个it = 4遍历循环
}
println(" END : "+::returnDemo2.name)//结果1、2、4、5、6、7
}
class Person {
var lastName: String = "zhang"
get() = field.toUpperCase() // 将变量赋值后转换为大写
set
var no: Int = 100
get() = field // 后端变量
set(value) {
if (value < 10) { // 如果传入的值小于 10 返回该值
field = value
} else {
field = -1 // 如果传入的值大于等于 10 返回 -1
}
}
var heiht: Float = 145.4f
private set
}
// 测试
fun main(args: Array<String>) {
var person: Person = Person()
person.lastName = "wang"
println("lastName:${person.lastName}")
person.no = 9
println("no:${person.no}")
person.no = 20
println("no:${person.no}")
}
输出结果为:
lastName:WANG
no:9
no:-1
10. 匿名内部类
class Test {
var v = "成员属性"
fun setInterFace(test: TestInterFace) {
test.test()
}
}
/**
* 定义接口
*/
interface TestInterFace {
fun test()
}
fun main(args: Array<String>) {
var test = Test()
/**
* 采用对象表达式来创建接口对象,即匿名内部类的实例。
*/
test.setInterFace(object : TestInterFace {
override fun test() {
println("对象表达式创建匿名内部类的实例")
}
})
}
11. 扩展函数(类似java中的装饰者设计模式)
// 扩展函数 swap,调换不同位置的值
fun MutableList<Int>.swap(index1: Int, index2: Int) {
val tmp = this[index1] // this 对应该列表,注意是对应脚标位置的值进行的替换
this[index1] = this[index2]
this[index2] = tmp
}
fun main(args: Array<String>) {
val l = mutableListOf(1, 2, 3)
// 位置 0 和 2 的值做了互换,!!!
l.swap(0, 2) // 'swap()' 函数内的 'this' 将指向 'l' 的值
println(l.toString())
}
实例执行输出结果为:
[3, 2, 1]
12. 扩展函数和成员函数一致,优先使用成员函数
class C {
fun foo() { println("成员函数") }
}
fun C.foo() { println("扩展函数") }
fun main(arg:Array<String>){
var c = C()
c.foo()
}
实例执行输出结果为:
成员函数
13. 扩展函数是静态解析的
在调用扩展函数时,具体被调用的的是哪一个函数,由调用函数的的对象表达式来决定的,而不是动态的类型决定的(这样说来其实感觉kotlin很无脑,给他指定是谁就是谁,不会由调用者来动态的决定)
open class C
class D: C()
fun C.foo() = "c" // 扩展函数 foo
fun D.foo() = "d" // 扩展函数 foo
fun printFoo(c: C) {
println(c.foo()) // 类型是 C 类
}
fun main(arg:Array<String>){
printFoo(D())
}
实例执行输出结果为:
c
14. 扩展属性
除了函数,Kotlin 也支持属性对属性进行扩展:
val List.lastIndex: Int
get() = size - 1
扩展属性允许定义在类或者kotlin文件中,不允许定义在函数中。初始化属性因为属性没有后端字段(backing field),所以不允许被初始化,只能由显式提供的 getter/setter 定义。
val Foo.bar = 1 // 错误:扩展属性不能有初始化器
扩展属性只能被声明为 val。
15. 在一个类内部你可以为另一个类声明扩展。
class D {
fun bar() { println("D bar") }
}
class C {
fun baz() { println("C baz") }
fun D.foo() {
bar() // 调用 D.bar
baz() // 调用 C.baz
}
fun caller(d: D) {
d.foo() // 调用扩展函数
}
}
fun main(args: Array<String>) {
val c: C = C()
val d: D = D()
c.caller(d)
}
实例执行输出结果为:
D bar
C baz
//在 C 类内,创建了 D 类的扩展。此时,C 被成为分发接受者,而 D 为扩展接受者。从上例中,可以清楚的看到,在扩展函数中,可以调用派发接收者的成员函数。
16. 分发接收者虚拟解析,扩展接收者静态解析
以成员的形式定义的扩展函数, 可以声明为 open , 而且可以在子类中覆盖. 也就是说, 在这类扩展函数的派 发过程中, 针对分发接受者是虚拟的(virtual), 但针对扩展接受者仍然是静态的。
open class D {
}
class D1 : D() { //1.扩展接收者
}
open class C { //2. 分发接收者
open fun D.foo() {
println("D.foo in C")
}
open fun D1.foo() {
println("D1.foo in C")
}
fun caller(d: D) {
d.foo() // 调用扩展函数
}
}
class C1 : C() {
override fun D.foo() {
println("D.foo in C1")
}
override fun D1.foo() {
println("D1.foo in C1")
}
}
fun main(args: Array<String>) {
C().caller(D()) // 输出 "D.foo in C"
C1().caller(D()) // 输出 "D.foo in C1" —— 分发接收者虚拟解析
C().caller(D1()) //为什么不是输出 D1.foo in C ? 实际输出D.foo in C —— 扩展接收者静态解析
C1().caller(D1()) //为什么不是输出 D1.foo in C1?实际输出 D.foo in C1
}
实例执行输出结果为:
D.foo in C
D.foo in C1
D.foo in C
17.外部类扩展函数为优先级最高
class MyClass {
companion object {
val myClassField1: Int = 1
var myClassField2 = "this is myClassField2"
fun companionFun1() {
println("this is 1st companion function.")
foo()
}
fun companionFun2() {
println("this is 2st companion function.")
companionFun1()
}
}
fun MyClass.Companion.foo() { //这个方法是有误的,给本类添加伴随扩展函数不就是自己的函数吗?在调用的时候会以外部扩展函数优先
println("伴随对象的扩展函数(内部)")
}
fun test2() {
MyClass.foo()
}
init {
test2()
}
}
val MyClass.Companion.no: Int
get() = 10
fun MyClass.Companion.foo() {
println("foo 伴随对象外部扩展函数")
}
fun main(args: Array<String>) {
println("no:${MyClass.no}") //输出 10
println("field1:${MyClass.myClassField1}") //输出 1
println("field2:${MyClass.myClassField2}") //输出this is myClassField2
MyClass.foo() //输出 伴随对象的扩展函数(内部)---错了
MyClass.companionFun2() //输出 this is 2st companion function. this is 1st companion function foo 伴随对象外部扩展函数
}
输出结果
no:10
field1:1
field2:this is myClassField2
foo 伴随对象外部扩展函数
this is 2st companion function.
this is 1st companion function.
foo 伴随对象外部扩展函数
18.泛型
fun main(args: Array<String>) {
val age = 23
val name = "runoob"
val bool = true
doPrintln(age) // 整型
doPrintln(name) // 字符串
doPrintln(bool) // 布尔型
}
fun <T> doPrintln(content: T) {
when (content) {
is Int -> println("整型数字为 $content")
is String -> println("字符串转换为大写:${content.toUpperCase()}")
else -> println("T 不是整型,也不是字符串")
}
}
输出结果为:
整型数字为 23
字符串转换为大写:RUNOOB
T 不是整型,也不是字符串
19. out使得类型参数协变,in使得类型参数逆变
out----协变类型参数用作输出,可以用作返回值但是无法作为入参的类型
in------逆变类型参数只能用作入参的类型,不能作为返回值(编译时期报错)
// 定义一个支持协变的类
class Runoob<out A>(val a: A) {
fun foo(): A {
return a
}
}
fun main(args: Array<String>) {
var strCo: Runoob<String> = Runoob("a")
var anyCo: Runoob<Any> = Runoob<Any>("b")
anyCo = strCo
println(anyCo.foo()) // 输出 a
}
// 定义一个支持逆变的类
class Runoob<in A>(a: A) {
fun foo(a: A) {
//此处添加返回值,在编译期就会报错
}
}
fun main(args: Array<String>) {
var strDCo = Runoob("a")
var anyDCo = Runoob<Any>("b")
strDCo = anyDCo
}
20. 枚举
enum class Color{
RED,BLACK,BLUE,GREEN,WHITE
}
fun main(args: Array<String>) {
var color:Color=Color.BLUE
println(Color.values())
println(Color.valueOf("RED")) // 转换指定 name 为枚举值,若未匹配成功,会抛出IllegalArgumentException
println(color.name)
println(color.ordinal)
}
自 Kotlin 1.1 起,可以使用 enumValues<T>() 和 enumValueOf<T>() 函数以泛型的方式访问枚举类中的常量 :
enum class RGB { RED, GREEN, BLUE }
inline fun <reified T : Enum<T>> printAllValues() {
print(enumValues<T>().joinToString { it.name })
}
fun main(args: Array<String>) {
printAllValues<RGB>() // 输出 RED, GREEN, BLUE
}
21.匿名对象的公有函数类型的成员返回的是any不能进行访问
class C {
// 私有函数,所以其返回类型是匿名对象类型
private fun foo() = object {
val x: String = "x"
}
// 公有函数,所以其返回类型是 Any
fun publicFoo() = object {
val x: String = "x"
}
fun bar() {
val x1 = foo().x // 没问题
val x2 = publicFoo().x // 错误:未能解析的引用“x”
}
}
22.定义一个被委托的类
该类需要包含 getValue() 方法和 setValue() 方法,且参数 thisRef 为进行委托的类的对象,prop 为进行委托的属性的对象
import kotlin.reflect.KProperty
// 定义包含属性委托的类
class Example {
var p: String by Delegate()
}
// 委托的类
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, 这里委托了 ${property.name} 属性"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$thisRef 的 ${property.name} 属性赋值为 $value")
}
}
fun main(args: Array<String>) {
val e = Example()
println(e.p) // 访问该属性,调用 getValue() 函数
e.p = "Runoob" // 调用 setValue() 函数
println(e.p)
}
输出结果为:
Example@433c675d, 这里委托了 p 属性
Example@433c675d 的 p 属性赋值为 Runoob
Example@433c675d, 这里委托了 p 属性
23.委托----Lazy延迟属性
val lazyValue: String by lazy {
println("computed!") // 第一次调用输出,第二次调用不执行
"Hello"
}
fun main(args: Array<String>) {
println(lazyValue) // 第一次执行,执行两次输出表达式
println(lazyValue) // 第二次执行,只输出返回值
}
执行输出结果:
computed!
Hello
Hello
24.委托—observable(观察者设计模式)
import kotlin.properties.Delegates
class User {
var name: String by Delegates.observable("初始值") {
prop, old, new ->
println("旧值:$old -> 新值:$new")
}
}
fun main(args: Array<String>) {
val user = User()
user.name = "第一次赋值"
user.name = "第二次赋值"
}
执行输出结果:
旧值:初始值 -> 新值:第一次赋值
旧值:第一次赋值 -> 新值:第二次赋值
25. 委托模式
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
class ResourceID() {
val image_id: String = "101"
val text_id: String = "102"
}
class ResourceLoader(id: ResourceID) {
val d: ResourceID = id
operator fun provideDelegate( thisRef: MyUI, prop: KProperty<*>): ReadOnlyProperty<MyUI, String> {
if(checkProperty(thisRef, prop.name)){
return DellImpl(d)
}else{
throw Exception("Error ${prop.name}")
}
}
private fun checkProperty(thisRef: MyUI, name: String):Boolean {
return name.equals("image") || name.equals("text")
}
}
class DellImpl(d: ResourceID) : ReadOnlyProperty<MyUI, String> {
val id: ResourceID = d
override fun getValue(thisRef: MyUI, property: KProperty<*>): String {
if(property.name.equals("image"))
return property.name+" "+id.image_id
else
return property.name+" "+id.text_id
}
}
fun bindResource(id: ResourceID): ResourceLoader {
var res = ResourceLoader(id);
return res
}
class MyUI {
val image by bindResource(ResourceID())
val text by bindResource(ResourceID())
//val webview by bindResource(ResourceID())
}
fun main(args: Array<String>) {
try{
var ui = MyUI()
println(ui.image)
println(ui.text)
}catch(e: Exception) {
println(e.message)
}
}
// 输出
/**
* image 101
* text 102
*/