kotlin简介

一. kotlin是什么?

kotlin是一种运行在java虚拟机上的静态编程语言,2011年,JetBrains推出了kotlin项目,2016年2月15日正式发布了第一个官方稳定版本V1.0,2017年在google I/O大会上,google正式宣布kotlin成为Android官方开发语言。

二、基本数据类型:

1、java基本数据类型

byte、short、int、long、float、double、char、boolean。

定义:int i = 0;

2、kotlin基本数据类型

Double、Float、Long、Int、Short、Byte、Char、Boolean。

定义:var i : Int = 0;//成员变量必须初始化

3、方法

fun method(arg:Int):Int{
return 0
}

void->unit

所有类的基类是Any,类定义:

public class A{}//类
open class A{}//类A 可继承,否则不可继承
class C:A(){}//c继承A,A必须是open

接口

interface TestInterface{
}
class C:TestInterface{}//实现接口,多个使用,分割

三、 优势

1、空指针问题

java示例:

public class Person {
    private List<Address> mAddressList;
    public static void main(String[] args) {
        Person person = new Person();
        if (person.mAddressList != null) {//1层判空
            for (Address address : person.mAddressList) {
                if (address != null){//二层判空
                    if (address.address1 != null){//三层判空
                        System.out.println(address.address1.length());
                    }
                }
            }
        }
    }
}

class Address {
    String address1;
}

kotlin代码实现:

class Person1 {
    var mAddressList: List<Address?>? = null//不再需要分号
}

class Address {
    var address1: String? = null
}
//方法 fun关键字,如果有返回值,加在方法名后面
fun main(args: Array<String>) :Unit {
    val person = Person1()
    person.mAddressList?.forEach {
        println(it?.address1?.length)
    }
}

说明:
(1)kotlin提供具体类型+?的类型,可以允许对应变量为null
(2)通过?.操作符可以解决空指针问题。
这种情况可以动态避免空指针问题,即在执行过程中避免。

(3)kotlin同时提供强制非空类型定义,如果违背,编译期间就会报错,如下所示:

class Address {
    var address1: String? = null
    fun setAddress(address: String) {//不允许为空
      //这里使用address就不需要判空,一定不为空
      print(address.length)//正确
    }
    fun setAddress2(address2:String?){//运行为空
      //这里使用address就需要判空,可能为空
        print(address2.length)//编译器报错,无法这么调用
        print(address2?.length)//正确,为null时打印null
        print(address2!!.length)//正确,为null时强制crash
    }
}

fun main(args: Array<String>) {
    val address = Address()
    var value:String? = null
    address.setAddress(value)//编译错误
    address.setAddress2(value)//编译通过
}

kotlin对于为null的对象,同时提供强制抛出异常的机制,如下:

val person:Person1? = null
    person?.address//person为null时不执行后续代码
    person!!.address//person为null时,抛出空指针异常

kotlin空指针潜在的问题

假如Person是java代码,kotlin调用上述java代码,示例:

fun main(args: Array<String>) {
    val person = Person()//Person是java代码
    person.mAddressList.forEach {//此时编译器并不会提示mAddressList可能为null !!
        println(it.address1.length)//任何一个环节空指针都会打印空
    }
}

纯kotlin代码本身存在的可能潜在的空指针问题

//kotlin中,所有的类默认都是不可继承的,除非使用open关键字修饰,这里因为使用了
//abstract,默认为open,所以没有加上
abstract class Person1 {
    abstract val address: Address
    init {
        address.toString()//空指针 crash
    }
}
class Student() : Person1() {
    override val address: Address = Address()
}
class Address//可以没有{}
fun main(args: Array<String>) {
    val person = Student()
}

2、数据类

在java中通常会定义一些纯粹保存数据的类,比如android中常见的对应于json的java对象,如下所示:
//java数据类代码

public class Person {
    public String name;
    public String address;
    public int age;
    //......
}

kotlin为我们提供了对应的data类,

data class Person1(var name: String, var age: Int, val address: String)

数据类的优势:
1、数据类重写了toString方法
2、数据类重写了equals和hasCode方法
3、数据类提供了copy方法
4、数据类提供了componetN方法

3.单例

object SingleInstance {//使用object来声明一个单例对象
}

对应于java中的单例代码:

//kotlin单例对应的java单例的写法
public class SingleInstance {
    private SingleInstance() {
    }
    public final static SingleInstance INSTANCE = new SingleInstance();
}

伴随对象

class MyClass {//类比于java的static
    companion object {//这就是伴随对象的定义
        fun test() {}
    }
}
//测试类
class Main {
    companion object {
        @JvmStatic//会被编译成真正的static方法
        fun main(args: Array<String>) {
            MyClass.test()//伴随对象的调用
            MyClass.Companion.test()//你也可以通过这种方式调用
        }
    }
}

4.扩展

kotlin扩展如下所示:

fun String.lastChar(): Char {//这里为String定义了一个扩展方法,该方法的功能就是获取字符串的最后一个字符
    return this[this.length - 1]//注意这里使用了this
}
//测试类,提供main方法
class Main {
    companion object {
        @JvmStatic fun main(args: Array<String>) {
            println("hello".lastChar())//注意这里,打印'o'
        }
    }
}

扩展解决的问题是java中大量的util类的问题,如:

import java.util.Collections;
Collections.swap(list, Collections.binarySearch(list
                , Collections.max(anthoerList)), Collections.max(list));

代码很啰嗦,通过扩展可以简化如下:

list.swap(list, binarySearch(list)
                , max(athoerList), max(list));

实际上是将util工具类完成的功能,回归类型本身。

5.强大的表达式、操作符、库方法

(1)if-else表达式
相较于java,除了完成正常的条件判断外,if-else可以做为表达式:

min = if (a < b) a else b//作为表达式使用

(2)when表达式

            val a = -1
            when (a) {
                1 -> println("a == 1")//注意,这即表示一个匹配条件,类似于switch中的case
                -1 -> println("a == -1")
                0 -> println("a == 0")
                else -> {//类似于switch中的default
                    print("a not match...")
                }
            }

(3)强大的函数:let、with、run、apply、also
let:

fun main(args: Array<String>) {
    var person: Person1? = null
    //不使用let
    person?.address
    person?.age
    person?.name
    //使用let: 针对一个可null的对象统一做判空处理
    person?.let {//最后一条语句作为返回值
        it.age
        it.address
        it.name
    }
}

with:

fun main(args: Array<String>) {
    var person: Person1 = Person1("", 0, "")
    with(person) {//可以省略具体的对象,最后一条语句作为返回值
        name
        age
        address
    }
}

run:

var person: Person1 = Person1("", 0, "")
    person.run {//run方法实际上结合了with和let,最后一条语句作为返回值
        name
        age
        address//address作为返回值
    }

apply

    var person: Person1 = Person1("", 0, "hha")
    var result = person.apply {//返回值为对象本身,故可以链式调用
        name//省略it
    }.apply {
        address
    }.apply {
        age
    }

also

    var result = person.also {//和let很像,不过返回值为对象本身,可以链式调用
       it.name//必须使用it指代,
    }.also {
        it.address
    }
    println(result)

map

    var map = mapOf(//只读
            "key1" to "value1",
            "key2" to "value2"
    )
//map的遍历,很简单
    map.forEach { key, value -> println("key: $key, value: $value") }
    var mutableMap = mutableMapOf(
            "key1" to "value1"
    )
    mutableMap.put("ke2", "value2")
    mutableMap.put("ke3", "value2")
//可以过滤
    val size = mutableMap.filterValues { it.equals("value2") }.size
    print(size)
}

arr

    var arr = arrayOf("1",2,3)
    arr[1] = 4
    arr.forEach {
        print(it)
    }

list

    val list = listOf("1","2",3)
    list.forEach {
        print(it)
    }
    val list2 = mutableListOf("1", 2)
    list2.add(3)
    list2.plus(list)
    list2.forEach {
        print(it)
    }

6.高阶方法和lambda表达式

在kotlin中,方法是一等公民。什么是一等公民?翻译成编程语言对应的意思就是:kotlin中的方法同一般的变量一样,可以作为方法参数、可以赋值给其他变量等等。
(1)高阶方法
高阶方法是指,那些入参类型包含方法类型或者返回值是个方法类型的方法。

fun sayHello(str: String, checkStr: (str: String) -> Boolean) {
    if (checkStr(str)) {
        println("pass...")
    } else {
        println("error...")
    }
}

(2)lambda表达式
他们所表达的场景就是,在没有显示定义方法的时候,我们可以通过这种方式生成一个具有同等形式、功能的方法。

val testStr2 = "test"
//调用前面的sayHello
    sayHello(testStr2, { str -> str.isNotEmpty() })//打印'pass...'
//相当于
fun checkStr(str: String): Boolean {
    return str.isNotEmpty()
}

//lambda表达式作为方法最后一个参数时还可以放在外部
    sayHello(testStr2) { str -> str.isNotEmpty() }//打印'pass...'

lambda语法:

//直接给sum赋值一个方法类型实例,等于后面就是标识的lambda表达式
 val sum = { x: Int, y: Int -> x + y }
//也可以显示定义sum的类型为(Int,Int)->Int的方法类型
val sum: (Int, Int) -> Int = { x, y -> x + y }

7.inline方法

//此时方法m1就是内联方法,使用了inline关键字修饰
    inline fun m1() {
        println("hello world")
    }
//测试方法
    fun test() {
        m1()
    }
}

8.中缀方法

//我们为Int类定义了一个中缀方法sum
infix fun Int.sum(i: Int): Int = this + i
fun main(args: Array<String>) {
    println(1 sum 2)//调用sum中缀方法
}

解构和ranges

解构

//必须是data类,data类提供了componentN方法
data class Person1(var name: String, var age: Int, val address: String) {
}
    val person:Person1 = Person1("name", 1, "address")
    val (name, age) = person//字段顺序不能变

ranges

fun main(args: Array<String>): Unit {
    val i = 0
    for (i in 1..10) {
        print(i)
    }
    val j = 0
    for(j in 10 downTo 2){
        print(j)
    }
    val k = 0
    for (k in 10 downTo 1 step 3){
        print(k)
    }
    val h = 0
    for (h in 10 until 3){
        print(h)
    }
}

协程

fun main(args: Array<String>) = runBlocking {
    GlobalScope.launch {//top-level级别的
        delay(1000L)
        println("world!")
    }
    println("hello ")
    delay(2000L)
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341