Kotlin 基础篇一

Ktlin 基础二

Kotlin运行原理

java虚拟机并不是和编写的java代码打交道,而是处理编译之后的class文件

Kotlin使用了新的编译规则生成class文件,只要class文件的符合规范java虚拟机就可以识别。

Kotlin的优势

1.Kotlin语法更加简洁,代码量可能会减少50%

2.Kotlin增加了很多高级语法特性,使得开发效率大大提升

3.Kotlin在语言安全性上方面下了很多功夫,几乎杜绝了空指针这个崩溃率最高的异常。

4.Kotlin和java 100%兼容,可以无缝只用java的三方库

var 与 val

var表示可变的变量 variable的简写

val 表示不可变的变量相当于final value的简写

使用这种定义变量的方式,那么编译器是怎么知道类型的这个得益于kotlin具有出色的类型推到机制

优先使用val 声明变量,当这个不能满足的时候再使用var

定义函数的方式

fun add(a:Int,b:Int):Int{
    return a+b;
}

add是函数名,括号里边的是参数,格式是:参数名:参数类型,如果不需要输入参数可以是一个空括号。

括号后边的是是返回值的类型,没有就不用写。语句的后边不需要添加分号

Kotlin的内置函数

fun largeNumber(a:Int,b: Int):Int{
    return max(a,b)
}

max就是kotlin的内置函数

Kotlin语法糖

当一个函数只有一行代码的时,Kotlin允许我们不必写函数体,可以直接将唯一的一行代码写在函数定义的尾部,中间使用等号连接即可,如上边的函数可以使用这个方式进行编写。

fun largeNumber(a:Int,b:Int):Int= max(a,b)

条件语句有两种实现方式:if和when。

if条件语句

Kotlin的if和java几乎是没有区别的,不同之处在于kotlin中的if多了一个额外的功能:可以有返回值的,返回值就是if语句每一条件的最后一行代码的返回值,如下面这个写法

fun largeNumber(a:Int,b:Int):Int{
    return if (a>b){
        a
    }else{
        b
    }
}

根据语法糖可以进一步精简

fun largeNumber(a:Int,b:Int):Int=if (a>b)a else b

这个就是kotlin 代码简洁的例子

when条件语句

when语句有点类似于java中的switch语句,但是比switch语句强大。

fun getScore(name:String) = when(name){
    "tom"->84
    "lili"->82
    "jack"->85
    "tong"->86
     else->0
}

省去了if判断,简洁清爽。

when语句还支持类型判断

fun checkType(num:Number):String{
    return when (num) {
        is Int -> "is int"
        is Double -> "is double"
        else -> "error type"
    }
}

类型判断代码中,is关键字就是类型匹配的核心,它相当于java 的instanceof关键字。Number 是kotlin内置的一个抽象类,Int、Long、Float、Double都是它的子类。

kotlin中判断字符串或者对象是否相等可以直接使用==,不用调用equals()方法。

循环语句

kotlin中跟java一样也提供了两种循环语句:while和for循环,while和java的完全一样。

其中对for循环做了很大幅度的修改,java中使用的for-i 循环在kotlin中别舍弃了,for-each被加强变成了for-in循环

kotlin 表示一个区间

val range=0..10;  //[0,10]

这个表示方式,两端都会包含

val range=0..10;  //[0,10]
for (i in range){
    println("i=$i");
}

上面的方式在当成数组的下标的时候不方便,因为最后一个数字是不包含的,可以采用这个方式

val range=0 until 10;  //[0,10)  这个是左闭右开的

这样就不包含最后的10了

for (i in range step 2){
    println("i=$i");
}

step 这个可以在循环的时候跳过某些元素

如果想创建一个降序的空间

val down=10 downTo 1  //[10,1]

Kotlin 面向对象

下面创建一个类

class Person {
    var name=""
    var age=0

    fun eat(){
        println(name+"is eating. he is "+age+"years old.")
    }
}

//实例化调用这个类
fun main(){
    val p=Person();  //声明一个对象
    p.name="tom"
    p.age=10
    p.eat()
}

kotlin本着最简化的设计原则,把new关键字和分号都省了

面向对象的一个重要的特性-继承

open class Person {
    var name=""
    var age=0

    fun eat(){
        println(name+"is eating. he is "+age+"years old.")
    }
}

class Student : Person() { //
    var studentNumber = 0   //学号
    var grade=0     //年级

}

上面写了一个Student 类继承Person类,继承只需要使用:就可以,不用再使用extends 关键字。

注意:Person类的声明变化,类前面加了一个open的关键字,如果不加这个关键字是不能被继承的。

在kotlin中所有的非抽象的类默认都是不允许被继承的,相当于java中给类加了一个final关键字。

继承本身带有侵入性,按照依赖倒置的原则,高层模块不应该继承底层模块都应该继承抽象的语义,好多时候java中没有这个语法限制,常常会违背这个设计原则。如果一个类不是专门为继承设计的,那么就应该主动加上final关键字,禁止它被继承。

这里还有一个点,就是父类后边的括号,为什么需要加括号?这里就涉及到kotlin中 主构造函数、次构造函数等方面的内容。

主构造函数将会是最常用的构造函数,每个类都会有一个默认的无参主构造函数,主构造函数的特点是没有函数体,直接定义在函数的后边。

class Student( val studentNumber:Int, val grade:Int) : Person() { 
    init {
        println("studentNumber is $studentNumber")
        println("grade is $grade")
    }
}

上面这个写法就相当于声明了主构造函数的带两个参数的,kotlin还提供了init结构体,所有主构造函数的逻辑可以写在里面。

这些跟父类的括号有什么关系呢,这就涉及java 继承特性的一个规定,子类的构造函数必须调用父类的构造函数。可是主构造函数并没有函数体,就没办法调用父类的构造函数了。有一个方法就可以放在init方法,好多情况下是不需要写init结构体的。

所以这里的括号就是子类主构造函数调用父类的那个构造函数,在继承的时候使用括号来指定。

次构造函数一般用不到,次构造函数跟主构造函数的区别是:次构造函数有函数体。

kotlin规定,当一个类既有主构造函数,也有次构造函数的时候,次构造函数必须调用柱构造函数。

次构造函数使用constructor进行定义。

class Student( var studentNumber:Int, var grade:Int) : Person() {
    //这个结构体,专门用于构造函数的调用
    init {
        println("studentNumber is $studentNumber")
        println("grade is $grade")
    }
    //这个是次构造函数
    constructor(studentNumber:Int):this(studentNumber,0)
    //这个是次构造函数
    constructor():this(0)

}

另外kotlin还允许自由次构造函数,没住构造函数的情况,这个情况父类的括号可以省了,由于没有主构造函数,次构造函数只能直接调用父类的构造函数

class Student : Person {
    //这个是次构造函数
    constructor(studentNumber:Int):super(){
        println("studentNumber is $studentNumber")
    }
}

kotlin中的接口

java中可以是单继承,可以有多个实现。kotlin也是这样的。

open class Person(name:String, age:Int) {
    var name=name
    var age=age

    fun eat(){
        println(name+"is eating. he is "+age+"years old.")
    }
}

class Student( name:String, age:Int) : Person(name,age),Study {
    override fun readBooks() {
        println("$name is read books")
    }
}

kotlin中实现一个接口,不再使用implements 这个关键字,统一使用冒号和逗号。

使用override关键字来重写父类或者接口中的函数。

另外kotlin还允许接口中定义默认实现,拥有了默认实现就不要求实现类必须重写这个方法了,可以选择重写。

kotlin类的可见性

修饰符 java kotlin
public 所有类可见 所有类可见(默认)
private 当前类可见 当前类可见
protected 当前类、子类,同一个包下的可见 当前类、子类
default 同一包下面的类可见(默认)
internal 同一个模块的类可见

internal是kotlin新增的一个关键字,这个是同一个模块中的类可见,应用场景:当我们开发一个模块给别人使用,有一些类只想内部调用,不想外部调用就可以使用这个关键字进行函数声明。

kotlin的数据类

java 声明一个数据实体类

public class CellPhone {
    
    String brand;
    
    double price;

    public CellPhone(String brand, double price) {
        this.brand = brand;
        this.price = price;
    }

    @Override
    public boolean equals(Object o) {
       if (o instanceof CellPhone){
           CellPhone other= (CellPhone) o;
           return other.brand.equals(brand)&&other.price==price;
       }
       return false;
    }

    @Override
    public int hashCode() {
        return (int) (brand.hashCode()+price);
    }

    @Override
    public String toString() {
        return "CellPhone{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}

重写了equals 和hashCode方法,有的时候不重写,当使用hashMap和hashCode的时候会有问题,toString是为了打印日志。

kotlin声明一个数据实体类

data class CellPhone(val brand:String, val price:Double)

一行搞定了,不管是打印数据还是使用HashMap和HashCode 都不会有问题。就是因为使用data关键字,就表明希望这个类是一个数据类,kotlin就把equals、hashCode、toString这些方法自动生成了,从而简化开发工作量。当类中没有别的实现,大括号也可以省略。

kotlin中的单例设计模式

java中的单例有饱汉式、饿汉式、双检测、匿名内部类、枚举等实现方式。

下面看kotlin的单例实现方式

object SingleTon {

    fun test(){
        println("单例测试")
    }
}

只需要将class关键字改成object ,使用这个关键字kotlin就会帮我们创建一个SingleTon的实例,并保证全局只有一份实例。

上面分享的这些内容,学习郭霖的书籍总结而来,感谢,希望能给初学者带来帮助,共同进步共同成长!

你可能感兴趣的:(Android,Kotlin,kotlin,android)