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)
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值