本文是对<<Kotlin in Action>>
的学习笔记,若是须要运行相应的代码能够访问在线环境 try.kotlinlang.org,这部分的思惟导图为: java
在kotlin
中,建立HashSet
、ArrayList
和HashMap
的方法以下: 正则表达式
Java
集合类:
Java
集合使
kotlin
能够更容易地与
Java
代码交互。当从
Kotlin
调用
Java
函数的时候,不用转换它的集合类来匹配
Java
的类,反之亦然。
在这些集合对象上,咱们除了可使用Java
当中定义的基本函数之外,还可使用kotlin
提供的扩展方法,例以下面的last
和max
: 数组
下面,咱们定义一个函数,它的做用的是打印集合当中的元素,并指定元素之间添加分隔符、前缀和后缀: bash
在上面的例子中,咱们指定了分隔符、前缀和后缀三个参数,可是对于这个函数的使用者来讲,若是不去看这些函数的声明,很难看出这些String
类型的含义,这时候就可使用 命名参数 的方法来调用,这有两点好处:函数
下面,咱们使用命名参数,并在不改变函数定义的状况下,改变传入参数的顺序,也能够获得和上面相同的运行结果: 学习
对于命名参数,有如下几点须要注意:ui
Java
函数时,不能使用命名参数。在kotlin
中,能够在声明函数的时候,指定参数的默认值,这样就能够避免建立重载的函数,例如上面的例子,咱们能够在 定义函数 时,指定三个String
的默认值,而在 调用函数 的时候,若是没有传递这些参数,那么将会采用默认值: spa
在Java
中,全部的代码都须要写做类的函数,可是在项目中,不少代码并不能归属到类中,这时候咱们通常会定义一个xxUtils
类,并在其中声明static
的静态方法。3d
在kotlin
中,咱们能够把这些函数直接放到代码文件的顶层,不用从属于任何的类,这些放在文件顶层的函数仍然是包内的成员,若是你须要从包外访问它,则须要import
,但再也不须要额外包一层。code
若是咱们想要在Java
中调用这些顶层函数,则须要经过Kotlin
根据包含函数的文件的名称生成的类,例如咱们有两个文件
KotlinMethod.kt
:fun kotlinFunc() {}
复制代码
JavaCallKotlin.java
:public class JavaCallKotlin {
public JavaCallKotlin() {
KotlinMethodKt.kotlinFunc();
}
}
复制代码
前者包含一个顶层函数,那么在Java
中,就会根据该文件名生成一个{文件名}Kt
的类型,再经过这个类来调用这个顶层函数。
若是不想使用默认的类名,能够在.kt
文件的开头加上@file:JvmName("类名")
的注解。
和函数同样,属性也能够放到文件的顶层。默认状况下,顶层属性和其余任意的属性同样,是经过访问器暴露给Java
使用的(若是是val
就只有一个getter
,若是是var
就对应getter
和setter
)。若是想要把一个常量以public static final
的属性暴露给Java
,可使用const
来修饰它。
package com.demo.lizejun.kotlinsample.chapter1
//不可变。
val kotlinVal = "kotlinValue"
//可变。
var kotlinVar = "kotlinVariable"
//常量。
const val kotlinConst = "kotlinConst"
//顶层函数。
fun kotlinFunc() {}
复制代码
在Java
中,分别经过如下几种方式来访问或者修改这几个顶层属性:
package com.demo.lizejun.kotlinsample.chapter3;
import com.demo.lizejun.kotlinsample.chapter1.KotlinMethodKt;
public class JavaCallKotlin {
public JavaCallKotlin() {
KotlinMethodKt.kotlinFunc();
//不可变。
KotlinMethodKt.getKotlinVal();
//可变。
KotlinMethodKt.setKotlinVar("newKotlinVar");
KotlinMethodKt.getKotlinVar();
//常量。
String kotlinConst = KotlinMethodKt.kotlinConst;
}
}
复制代码
扩展函数 实际上是一个类的成员函数,只不过它定义在类的外面,咱们所须要作的,就是在声明扩展函数的时候,把须要扩展的类或者接口的名称,放到它的前面,用来调用这个扩展函数的对象,就叫作 接收者对象。
在扩展函数中,能够直接访问被扩展的类的其它方法和属性,就好像是在这个类本身的方法中访问它们的同样,可是扩展函数不容许你打破它的封装性,扩展函数不能访问私有的或者是受保护的成员。
下面咱们给String
类添加一个扩展函数,返回它的最后一个字符:
若是须要在Java
中调用扩展函数,那么把接收者对象做为第一个参数传进去便可:
//接收者对象做为第一个参数。
char lastChar = KotlinMethodKt.last("Kotlin");
复制代码
这里假设咱们有两个类,View
和Button
,其中Button
继承于View
,咱们给这两个类都添加一个名为showOff
的扩展函数。
Button
的对象,可是
Kotlin
会把扩展函数当作静态函数来对待,所以
扩展函数不存在重写。
扩展属性提供了一种方法,用来扩展类的API
,能够用来访问属性,用的是属性语法而不是函数的语法,尽管他们被称为属性,但它们没有任何状态,由于没有合适的地方来存储它们。
如今,咱们给StringBuilder
添加一个可读写的属性lastChar
,用于获取或者改变它的最后一个字符,包含如下几点要素:
var/val
关键字开头var
那么提供get()/set(value : T)
方法,而若是是val
属性,那么提供get()
方法,其中T
为属性的类型。使用关键字 vararg,能够用来声明一个函数将有可能有任意数量的参数,下面例子中,咱们定义一个能够接收可变数量Int
类型的函数,以后和在Java
中同样,它会被转换为[I
的整型数组类型:
*
操做符进行解包:
中缀调用 不是特殊的内置结构,而是一种特殊的函数调用。在中缀调用中,没有添加额外的分隔符,函数名称是直接放在目标对象名称和参数之间。例如咱们声明了一个to
函数。
//通常函数调用。
1.to("One")
//中缀调用。
1 to "One"
复制代码
中缀调用能够与 只有一个参数的函数 一块儿使用,不管是普通的函数仍是扩展函数,要容许使用中缀符号调用函数,须要使用infix
修饰符来标记它,下面是一个建立Person
的函数,咱们采用了扩展函数的方法,这里的Any
是Kotlin
中全部类的父类,和Java
中的Object
相同:
在Java
中,咱们会使用split
来分割字符串,它接受一个正则表达式做为参数。可是当咱们想分割"."
时,会获得一个空的数组,由于.
号表示任何字符的正则表达式。 而在kotlin
中,它提供了一个接受Regex
类型的重载函数,这样确保了当有一个字符串传递给这些函数的时候,不会被当作正则表达式,咱们可使用扩展函数toRegex
将字符串转换为正则表达式。
假设有下面这个字符串
/Users/yole/kotlin-book/chapter.adoc
复制代码
咱们须要经过这个字符串获取到chapter.adoc
的目录、文件名和扩展名,若是使用扩展函数,那么代码以下:
.
模式从字符串的一开始就进行匹配,因此第一组(.+)
包含最后一个斜线以前的子串,这和子串包含全部前面的斜线,由于它们匹配”任何字符“的模式。在Java
的一个函数当中,有可能存在重复代码,例如在注册模块中,可能须要校验输入的多个字段是否有效,那么校验的逻辑就能够提取出一个函数,而Kotlin
就提供了一种方法:能够在函数中嵌套这些提取的函数,局部函数定义方式和普通函数是相同的。