文章目录

  • 简介
  • 基本语法
  • Kotlin标准库
  • 基本类型
  • null 安全
  • 字符串类型
  • 类型别名


简介

  1. Kotlin 来源于一个岛屿(属于俄罗斯)的名字,全称是 Kotlin Island,是英语【科特林岛】之意
  2. Kotlin是一门静态类型编程语言,Kotlin支持JVM平台(主要针对JVM平台)、 Android平台 、 浏览器JS运行环境、本地机器码(通过LLVM)等 。
  3. 云端IDE环境http://kotlinlang.org/
  4. 安装
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

基本语法

  1. Kotlin严格区分大小写
  2. Kotlin与java不同,Kotlin支持函数式编程,因此只需要一个main函数作为函数入口,main函数不需要放在任何类中。
  3. Kotlin源码需要使用Kotlinc或者kotlinc-jvm命令进行编译
  4. java语言的多行注释不支持嵌套,而Kotlin的多行注释支持嵌套
/*
      外层注释
          /*
          内部注释
          */
     */
  1. kotlin不强制要求每条语句必须使用分号结尾,如果在一行写多条独立的语句,需要使用分号结尾
//kotlin不强制每条语句必须使用分号结尾
var name = "jannal"
//如果一行内多条语句,需要使用分号分割
var a = "a";var b = "b"
  1. kotlin允许一条语句可以跨行,字符串和变量名不能跨行
//允许一条数据可以跨多行,字符串和变量名不能跨多行
var result =
        name.toString()
//下面两种都无法编译通过
var res
        lt = name.toString()

var name ="aaaa
        bbbb"
  1. []分割符:索引运算符,主要用于数组的索引、List集合的索引、Map集合的Key
  2. kotlin的关键字
  • 硬关键字:无论在什么情况下都不能用作标识符
  • 软关键字:可以在它们不起作用的上下文中用作标识符
  • 修饰关键字:可以在代码中用作标识符
  1. 声明变量
语法:  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"
  1. 如果直接在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标准库

  1. Kotlin核心类库包含
kotlin-reflect.jar
kotlin-runtime.jar:该组件是对JDK类库的二次封装
  1. 除了核心类库外,kotlin还有一个jar包
kotlin-plugin.jar:插件接口,只有接口没有实现
  1. kotlin-runtime.jar是kotlin运行时组件,当Kotlin程序被打包编译后,kotlin-runtime.jar也会一起被编译进目标程序包。而kotlin-plugin.jar则不会被编译进目标程序包
  2. kotlin-plugin.jar:此包中都是接口,没有实现。编译器负责对这些方法进行解析和转义,将这些方法最终翻译成对应的java字节码逻辑,并调用对应java核心类库中的功能函数来实现这些方法。

基本类型

  1. 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
  1. Kotlin中的整型不是基本类型(java分基本类型和包装类型),都是引用类型(Kotlin中所有类型都是引用类型)。Byte、Short、Int、Long都继承了Number类型,因此4种类型都可以调用方法、访问属性
  2. kotlin是null安全的语言ByteShortIntLong 都不能接收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)
  1. Kotlin的整数数值有3种表示方式
  • 十进制
  • 二进制:0b或0B开头的整数数值
  • 十六进制:0x或0X开头的整数数值
  • Kotlin不支持八进制的整数
  1. kotlin中的"=="
  • "=="等于运算,比较的是值不是引用。这点与java不同,相当于java的equals
  • "==="不仅比较值还比较引用

null 安全

  1. 非空类型与可空类型,!!.是断言调用
//安全调用
    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)
  1. 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?)
}
  1. Elvis运算符"?:":给定一个在空的情况下的默认值
var d = null
    var c = d?:"我是空"

字符串类型

  1. Kotlin的字符串有两种字面值:
  • 转义字符串:转义字符串可以有转义字符,类似java的字符串
  • 原始字符串:可以包含任意换行和文本。使用3个引号引起来,与python一样
  1. 案例
/**
 * 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)


}

类型别名

  1. Kotlin提供了类似C语言种typedef的功能。可以为已有的类型指定另一个可读性更强的名字。
typealias 类型别名 = 已有类型
  1. 案例
/**
 * 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 {

    }
}