Kotlin入坑基础篇一

Kotlin入坑的理由:

1,大大减少Java样板代码;
2,避免空指针异常等;
3,充分利用JVM,Android现有的库,和JAVA可以完全兼容;
4,Google推荐为Android开发的首选;
5,编译器的良好支持。

我们现在在新功能或者新项目中使用kotlin语言,而旧的项目只需要简单的维护的则继续使用java语言。不管怎样,你都可以尝试使用kotlin去编程。

Kotlin的使用

函数

函数定义使用关键字 fun,参数格式为:参数 : 类型

/**
 * 计算两个数的差,返回类型为Int
 */
fun testSub(a: Int, b: Int): Int {
    return a - b
}

kotlin语言默认支持lambda表达式

// 使用lambda表达式
fun testLambda() {
    val sumLambda: (Int, Int) -> Int = {x,y -> x+y}
    println(sumLambda(1,2))  // 输出 3
}

变长参数测试

 fun testVararg(vararg v:Int){
        for(vt in v){
            print(vt)
        }
    }
    
    fun testVar(){
        testVararg(1,2,3)
    }

此外,kotlin还提供了便捷的字符串模板

/**
 * 字符串模板
 */
fun testTemp() {
    val s = "kotlin"
    val curStr = "我正在使用$s"
    print(curStr)
}

打印出来是”我正在使用kotlin“,可以省去java的字符串拼接;
通过上面的例子发现kotlin省略了;号的结束符号,此外kotlin定义字段的时候,只有varval两个修饰符,var表示可变变量定义,val表示不可变变量定义和Java中的final修饰的变量类似,并且kotlin可以声明变量的时候不指定变量类型,由编译器自动推断。

循环(for和while)

/**
 * for循环
 */
fun testFor() {
    for (i in 1..4) {
        print(i)
    }

    for (i in 1..4 step 2) {
        print(i)
    }

    //对集合进行迭代
    val items = listOf("apple", "banana", "kiwi")
    for(item in items){
        println(item)
    }

    for(index in items.indices){
        println("item at $index is ${items[index]}")
    }

}
/**
* 使用两种while遍历
*/
fun testWhile() {
    var x = 5
    while (x > 0) {
        println( x--)
    }

    var y = 5
    do {
        println(y--)
    } while(y>0)
}

条件语句(if和when)

值得注意的是kotlin中并没有swith语句,而使用了when替代;

/**
 * when 将它的参数和所有的分支条件顺序比较,直到某个分支满足条件。
 * 类似于switch
 */
fun testWhen(x: Int) {
      when (x) {
        is Int -> print(x.toString())
        else -> {
            print("不是int类型")
        }
    }
}

一个 if 语句包含一个布尔表达式和一条或多条语句。
kotlin中使用以下的表达式来替换java中的三元操作符:

// 作为表达式
val max = if (a > b) a else b

使用 in 运算符来检测某个数字是否在指定区间内

/**
* 使用区间
*/
fun testIf() {
    val x = 5
    if (x in 1..8) {
        println("x 在区间内")
    }
}

Kotlin中的对象和类

Kotlin中的类都是继承Any类(注意:并不是Object),它是所有类的超类,对于没有超类型声明的类是默认超类,Kotlin中与Java相同只能使用单继承。constructor为构造函数,init函数里面可以进行初始化操作。

class Person constructor(firstName: String) {
    init {
        println("FirstName is $firstName")
    }
}

下面来看看对象和类的使用

/**
 * 接口里面的成员变量默认为open类型
 * kotlin接口与java 8类似,可以在接口里面实现方法
 */
interface TestInterface {
    fun test() {
        print("TestInterface接口中的test()调用")
    }
}

/**
 * 类属性修饰符
 * abstract    // 抽象类
 * final       // 类不可继承,默认属性
 * enum        // 枚举类
 * open        // 类可继承,类默认是final的
 * annotation  // 注解类
 *
 * 访问权限修饰符
 * private    // 仅在同一个文件中可见
 * public     // 所有调用的地方都可见
 * internal   // 同一个模块中可见
 *  没有显式定义访问修饰符,默认为“public ”,对所有可见。
 */
open class Outer {
    private val bar: Int = 1
    private val name: String = "123456"

    class Nested {
        fun foo(): String {
            val curString: String = "123"
            return curString
        }
    }

    inner class Inner {
        fun innerTest(): String {
            return [email protected]
        }
    }

    open fun setInterface(test: TestInterface) {
        test.test()
    }

    open fun test() {

    }
}

/**
 * Kotlin也只能单继承
 */
class OuterImpl : Outer(), TestInterface {
    /**
     * 如果继承和实现的方法中,有同样的test方式,需要这样调用父类或者接口的方法
     * 另外:属性重写使用 override 关键字,属性必须具有兼容类型,每一个声明的属性都可以通过初始化程序或者getter方法被重写
     * 你可以用一个var属性重写一个val属性,但是反过来不行。因为val属性本身定义了getter方法,重写为var属性会在衍生类中额外声明一个setter方法
     */
    override fun test() {
        super.test()
        super.test()
    }

    override fun setInterface(test: TestInterface) {
        super.setInterface(test)
    }
}

/**
 * 测试
 */
fun testOuter(): String {
    var curStr = Outer.Nested().foo()// 调用格式:外部类.嵌套类.嵌套类方法/属性
    val curName = Outer().Inner().innerTest()//调用内部类
    //匿名内部类
    Outer().setInterface(object : TestInterface {
        override fun test() {
            print("这里是一个匿名内部类")
        }
    })
    OuterImpl().setInterface(object : TestInterface {
        override fun test() {
            print("这里使用了继承实现匿名内部类")
        }
    })
    return "Outer.Nested().foo()中的curString=${Outer.Nested().foo()}   Outer().Inner().innerTest()中name=$curName"
}

var curStr = Outer.Nested().foo()// 调用格式:外部类.嵌套类.嵌套类方法/属性
val curName = Outer().Inner().innerTest()//调用内部类
值得注意的是以上调用方式的不同。

Kotlin接口

Kotlin 接口与 Java 8 类似,使用 interface 关键字定义接口,允许方法有默认实现:

interface CustomInterface {
    fun testOne()    // 未实现
    fun testTwo() {  //已实现
      // 可选的方法体
      println("testTwo()")
    }
}

接口中的属性只能是抽象的,不允许初始化值,接口不会保存属性值,实现接口时,必须重写属性

interface CustomInterface{
    var name:String //name 属性, 抽象的
}
 
class CustomImpl:CustomInterface{
    override var name: String = "Hubery" //重载属性
}
伴生对象

类内部的对象声明可以用 companion 关键字标记,这样它就与外部类关联在一起,我们就可以直接通过外部类访问到对象的内部元素。另外一个类里面只能够有一个伴生对象,也就是只能有一个companion修饰符。

java中我们常常使用static,而kotlin里面没有这个而使用伴生对象替代。不过并不完全相等。

companion object {
        val EXTRA_ORDER_ID = "order_id"
}

类似于Java中如下定义 :

public static final String EXTRA_ORDER_ID = "extra_order_id";

需要注意的是:在kotlin语言中別的类需要访问就直接 类名.字段名访问就行,而在java中调用kotlin的EXTRA_ORDER_ID,在这里就需要使用
类名.Companion.getEXTRA_ORDER_ID()

伴生对象的成员看起来像其他语言的静态成员,但在运行时他们仍然是真实对象的实例成员。比如还可以实现接口:

interface CustomInterface {
    fun create(): T
}
class DemoClass {
    companion object : CustomInterface {
        override fun create(): DemoClass = DemoClass ()
    }
}
数据类和密封类
数据类

kotlin使用data来修饰的只包含数据的类。
json字符串{"key":123,"title":"This is title"}
使用kotlin实现:

data class Bean(
        @SerializedName("key") val key: Int,
        @SerializedName("title") val title: String
)

使用java显示

public class Bean{
    @SerializedName("key")
    private int key;
    @SerializedName("title")
    private String title;

    public int getKey() {
        return key;
    }

    public void setKey(int key) {
        this.key = key;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

看上面两段代码,发现kotlin的代码会简洁很多,特别是字段非常多的时候。

密封类

密封类用来表示受限的类继承结构:当一个值为有限几种的类型, 而不能有任何其他类型时。在某种意义上,他们是枚举类的扩展:枚举类型的值集合 也是受限的,但每个枚举常量只存在一个实例,而密封类 的一个子类可以有可包含状态的多个实例。
声明一个密封类,使用 sealed 修饰类,密封类可以有子类,但是所有的子类都必须要内嵌在密封类中。 此外,sealed 不能修饰 interface ,abstract class(会报 warning,但是不会出现编译错误)

sealed class SealedDemo
data class Const(val number: Double) : SealedDemo()
data class Sum(val s1: SealedDemo, val s2: SealedDemo) : SealedDemo()
object NotANumber : SealedDemo()
fun eval(SealedDemo: SealedDemo): Double = when (SealedDemo) {
    is Const -> SealedDemo.number
    is Sum -> eval(SealedDemo.s1) + eval(SealedDemo.s2)
    NotANumber -> Double.NaN
}

密封类的关键好处在于使用 when 表达式 的时候,如果能够 验证语句覆盖了所有情况,就不需要为该语句再添加一个 else 子句了。

Kotlin入坑基础篇二

你可能感兴趣的:(Kotlin入坑基础篇一)