文章目录
- 简介
- 基本语法
- Kotlin标准库
- 基本类型
- null 安全
- 字符串类型
- 类型别名
简介
- 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 {
}
}