简介
-
Kotlin 来源于一个岛屿(属于俄罗斯)的名字,全称是 Kotlin Island,是英语【科特林岛】之意
-
Kotlin是一门静态类型编程语言,Kotlin支持JVM平台(主要针对JVM平台)、 Android平台 、 浏览器JS运行环境、本地机器码(通过LLVM)等 。
-
云端IDE环境http://kotlinlang.org/
-
安装
1. 安装JDK(kotlin Compiler是直接依赖java命令的) 2. 解压kotlin安装包到目录/Volumes/P/develope/kotlinc $ → tree -d . ├── bin ├── lib └── license └── third_party └── testdata 3. 配置环境变量 export KOTLIN_HOME=/Volumes/P/develope/kotlinc export PATH=$PATH:$JAVA_HOME/bin::$KOTLIN_HOME/ 4. 验证 $ kotlinc Welcome to Kotlin version 1.2.51 (JRE 1.8.0_45-b14) Type :help for help, :quit for quit
基本语法
-
Kotlin严格区分大小写
-
Kotlin与java不同,Kotlin支持函数式编程,因此只需要一个main函数作为函数入口,main函数不需要放在任何类中。
-
Kotlin源码需要使用Kotlinc或者kotlinc-jvm命令进行编译
-
java语言的多行注释不支持嵌套,而Kotlin的多行注释支持嵌套
/*
外层注释
/*
内部注释
*/
*/
-
kotlin不强制要求每条语句必须使用分号结尾,如果在一行写多条独立的语句,需要使用分号结尾
//kotlin不强制每条语句必须使用分号结尾 var name = "jannal" //如果一行内多条语句,需要使用分号分割 var a = "a";var b = "b"
-
kotlin允许一条语句可以跨行,字符串和变量名不能跨行
//允许一条数据可以跨多行,字符串和变量名不能跨多行 var result = name.toString() //下面两种都无法编译通过 var res lt = name.toString() var name ="aaaa bbbb"
-
[]分割符:索引运算符,主要用于数组的索引、List集合的索引、Map集合的Key
-
kotlin的关键字
- 硬关键字:无论在什么情况下都不能用作标识符
-
软关键字:可以在它们不起作用的上下文中用作标识符
-
修饰关键字:可以在代码中用作标识符
-
声明变量
语法: var|val 变量名 [:类型] [=初始值] //声明变量显式指定类型 var age: Int //声明变量时指定初始值,编译器会根据初始值确定该变量的类型为String var username = "jannal" age = 10 //声明变量指定类型也指定初始化值 var height: Int = 100 //声明变量指定的类型与初始值类型不一致,此时报错 //var width :Int = "1000" //val 声明的变量是不可变的(相当于java中的final) val password = "123456" //password = "aaaa"
-
如果直接在kotlin程序中定义变量、函数,kotlin将会自动生成一个名为**“文件名+Kt”**的类,并将变量转换为该类的静态的getter、setter方法(val只有getter),函数则转换为该类的静态方法。比如创建一个
A.kt
文件
```java
package cn.jannal.kotlin.base
var aa = 100
fun aa(): String {
return "a"
}
```
会生成 `cn.jannal.kotlin.base.AKt.class`字节码文件,即在当前目录不能再定义一个同名的类
```java
// class version 52.0 (52)
// access flags 0x31
public final class cn/jannal/kotlin/base/AKt {
// compiled from: A.kt
@Lkotlin/Metadata;(mv={1, 1, 13}, bv={1, 0, 3}, k=2, d1={"\u0000\u0010\n\u0000\n\u0002\u0010\u0008\n\u0002\u0008\u0004\n\u0002\u0010\u000e\n\u0000\u001a\u0006\u0010\u0000\u001a\u00020\u0006\"\u001a\u0010\u0000\u001a\u00020\u0001X\u0086\u000e\u00a2\u0006\u000e\n\u0000\u001a\u0004\u0008\u0002\u0010\u0003\"\u0004\u0008\u0004\u0010\u0005\u00a8\u0006\u0007"}, d2={"aa", "", "getAa", "()I", "setAa", "(I)V", "", "kotlin-base_main"})
// access flags 0xA
private static I aa
// access flags 0x19
public final static getAa()I
L0
LINENUMBER 3 L0
GETSTATIC cn/jannal/kotlin/base/AKt.aa : I
IRETURN
MAXSTACK = 1
MAXLOCALS = 0
// access flags 0x19
public final static setAa(I)V
L0
LINENUMBER 3 L0
ILOAD 0
PUTSTATIC cn/jannal/kotlin/base/AKt.aa : I
RETURN
L1
LOCALVARIABLE <set-?> I L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x19
public final static aa()Ljava/lang/String;
@Lorg/jetbrains/annotations/NotNull;() // invisible
L0
LINENUMBER 5 L0
LDC "a"
ARETURN
MAXSTACK = 1
MAXLOCALS = 0
// access flags 0x8
static <clinit>()V
L0
LINENUMBER 3 L0
BIPUSH 100
PUTSTATIC cn/jannal/kotlin/base/AKt.aa : I
RETURN
MAXSTACK = 1
MAXLOCALS = 0
}
```
Kotlin标准库
-
Kotlin核心类库包含
kotlin-reflect.jar kotlin-runtime.jar:该组件是对JDK类库的二次封装
-
除了核心类库外,kotlin还有一个jar包
kotlin-plugin.jar:插件接口,只有接口没有实现
-
kotlin-runtime.jar
是kotlin运行时组件,当Kotlin程序被打包编译后,kotlin-runtime.jar
也会一起被编译进目标程序包。而kotlin-plugin.jar
则不会被编译进目标程序包 -
kotlin-plugin.jar
:此包中都是接口,没有实现。编译器负责对这些方法进行解析和转义,将这些方法最终翻译成对应的java字节码逻辑,并调用对应java核心类库中的功能函数来实现这些方法。
基本类型
-
4种四种
- Byte: 8位,-128~127,兼容java的byte和Byte
- Short:16位,-215~215-1,兼容java的short和Short
- Int:32位,-231~231-1,兼容java的int和Integer类型
- Long:64位,-263~263-1,兼容java的long和Long类型
//当直接给出一个较大的整数时,该整数默认可能就是Long型,赋值给Int所以会编译报错 //var intValue: Int = 2999999999
-
Kotlin中的整型不是基本类型(java分基本类型和包装类型),都是引用类型(Kotlin中所有类型都是引用类型)。Byte、Short、Int、Long都继承了Number类型,因此4种类型都可以调用方法、访问属性
-
kotlin是null安全的语言Byte、Short、 Int、 Long 都不能接收null值, 如果要存储null值,应该使用Byte?、 Short?、 Int?、 Long?。
- Int类型会被映射为java中int类
- Int?类型会被映射为java中的Integer类(包装类型)。Kotlin允许在已有类型后面添加**?,相当于对原有类型进行了扩展,带?**的数据类型可支持被赋予null值。Int?类型是Int类型的扩展
var nullable: Int? = null var p1: Int = 200; var p2: Int = 200 //true println(p1 === p2); var p3: Int? = 200; var p4: Int? = 200 //false println(p3 === p4); //true == 相当于equals println(p3 == p4); //安全调用 var user: String? = "jannal" //6 println(user?.length) user = null //null println(user?.length)
-
Kotlin的整数数值有3种表示方式
- 十进制
- 二进制:0b或0B开头的整数数值
- 十六进制:0x或0X开头的整数数值
- Kotlin不支持八进制的整数
-
kotlin中的"=="
- "=="等于运算,比较的是值不是引用。这点与java不同,相当于java的equals
- "==="不仅比较值还比较引用
null 安全
-
非空类型与可空类型,
!!.
是断言调用//安全调用 var user: String? = "jannal" //6 println(user?.length) user = null //null println(user?.length) var arr: Array<String?> = arrayOf("a", "b", "c", null, "", "d") for (item in arr) { //当item不为null时才调用 item?.let { println(it) } } //如果?:左边的表达式不为null,则返回左边表达式的值,否则返回?:右边的值 var b: String? = "jannal" var len = b?.length ?: -1 //强制调用(!!),无论是否是为null都调用 println(b!!.length) b = null //引发空指针异常 //println(b!!.length)
-
null对应的类型
fun main() { //true println(null == null) //false println(null != null) //false println(null is Any) //true println(null is Any?) //false println(null is Nothing) //true println(null is Nothing?) }
-
Elvis运算符"?:":给定一个在空的情况下的默认值
var d = null var c = d?:"我是空"
字符串类型
-
Kotlin的字符串有两种字面值:
- 转义字符串:转义字符串可以有转义字符,类似java的字符串
- 原始字符串:可以包含任意换行和文本。使用3个引号引起来,与python一样
-
案例
/** * kotlin的String与java的String并不是一个类 * @author jannal **/ fun main(args: Array<String>) { var username = "jannal" //根据索引访问字符 println(username[0]) println(username[1]) println(username[4]) //遍历字符串中的每个字符 for(c in username){ println(username) } //原始字符串 var txt = """ |a, |b, |c, """.trimMargin() //默认使用|分隔,|之前的会被忽略 println(txt) txt=""" %a, %b, %c, """.trimMargin("%") //指定使用%分隔 println(txt) //字符串模板$或者${},$简单变量,${}表达式 var desc1 = "我的名字是:$username" println(desc1) var desc = "我的名字是:${username}" println(desc) //模板中调用方法 desc = "我的名字长度:${username.length}" println(desc) }
类型别名
-
Kotlin提供了类似C语言种typedef的功能。可以为已有的类型指定另一个可读性更强的名字。
typealias 类型别名 = 已有类型
-
案例
/** * typealias 类型别名 = 已有类型 * 为已有的类型指定另一个可读性更强的名字,对于缩短集合类型比较好 * 内部类起一个更短的名字 * @author jannal **/ typealias NodeSet = Set<String> fun main(args: Array<String>) { var person = Person() val d: KClass<Person> = Person::class val s: KClass<out Person> = person::class val x: Class<Person> = Person::class.java //获取的是一个属性,可以get()获取值,返回Class val kProperty1: KProperty1<Person, Class<Person>> = Person::javaClass val KProperty1: KProperty0<Class<Person>> = person::javaClass //获取Person类的class val javaClass: Class<Person.Companion> = Person.javaClass val javaClass1: Class<Person> = person.javaClass val kotlin: KClass<Person> = person.javaClass.kotlin val kotlin1: KClass<Person.Companion> = Person.javaClass.kotlin } class Person { var name: String = "" var age: Int = 0 companion object { } }