Kotlin详解:第一章,基本语法

一,简介

  • Kotlin是JetBrains开发的基于JVM的语言,Kotlin可以编译成Java字节码,也可以编译成JavaScript,方便在没有JVM的设备上运行。
  • 特点:比Java更安全,能够静态检测常见的陷阱。如:引用空指针。代码更易表现,书写方便,便于阅读。支持函数式编程,如:使用lambda表达式来更方便地解决问题。
  • Kotlin是一种现代化的语言,语法汇集了很多语言的优点,是未来编程的一种趋势。

二,开发环境

  • 开发软件:IntelliJ IDEA和AndroidStudio
  • IntelliJ IDEA下载地址:http://www.jetbrains.com/idea/download/#section=windows
  • AndroidStudio下载地址:https://developer.android.google.cn/studio/index.html
  • 如果是老版本需要手动安装Kotlin插件
    三,数据类型

(1),开始编写第一段代码,这里使用IntelliJ IDEA来讲解,创建一个Kotlin文件,Kotlin是以kt为后缀
这里写图片描述
然后写一个mian方法打印一句话
这里写图片描述
(2),基本数据类型

①,数据类型和Java一样也有integer,float,boolean,不同的是Kotlin都是以对象的形式出现的。

    val i: Int = 1 
    val f: Float = 1f
    val d: Double = 1.0 
    val l: Long = 1  
    val sh: Short = 1 
    val b: Boolean = true
    val s: String = "Hello Word"

    val i = 1 
    val f = 1f
    val d = 1.0 
    val l = 1  
    val sh = 1 
    val b = true
    val s = "Hello Word"

val代表常量,命名规则 :变量名+冒号+数据类型。上边代码效果是一样的,这里数据类型可以不写,编译器会自动识别。代码后边的分号也不是必须的。

②,在Java中可以隐式转换,一个int类型是可以直接赋值给double类型的。而Kotlin不能隐式转换,需要强转。

//Kotlin代码
val i: Int = 8
val d: Double = i.toDouble()

//Java代码
int i=8;
double d=i;

③,String可以像数组一样被访问,也可以迭代。

    val s = "Hello Word"
    val c = s[2]
    for(c in s){
        println(c)
    }
    

④,这里‘’‘’和Java中的‘’equals‘’是等价的。‘’=‘’和Java中的‘’==‘’是等价的

    val s: String = "Hello Word"
    val s1: String = String(charArrayOf('H', 'e', 'l', 'l','o', ' ', 'W', 'o', 'r', 'd'))
    println(s == s1) //打印结果 true
    println(s === s1)//打印结果 false

⑤,在Kotlin中引入了字符串模板,用“$”表示

    val num1 = 3
    val num2 = 4
    println("" + num1 + "+" + num2 + "=" + (num1 + num2))//java方式
    println("$num1+$num2=${num1 + num2}")//Kotlin方式

⑥,空类型安全
在Java中定义一个变量,调用变量时通常会进行空值判断,否则会有空指针的异常。而在Kotlin程序会对空类型进行检测,则不会出现空指针异常。如果想让变量为空,需要在变量后边加上?


    var name: String = null //这里编译器是不会通过的,不能是null
    var sex: String? = null // 这样是没问题的
    
    println(sex.length) //这样是不行的,编译不通过
    println(sex?.length) //这样没问题
    println(sex!!.length) // 注意操作符!!,只有在sex不为空的情况下才能使用,否则会抛异常

在集合中可以使用filterNotNull过滤掉null类型的数据

    val list : List<String?> = listOf(
            "red",
            "orange",
            "yellow",
            "gree",
            "blue",
            null
    )
    //过滤掉null
    val colors:List<String> = list.filterNotNull()

⑦,在Java中有基本类型和装箱类型,如:int基本类型,Integer装箱类型。Kotlin中不用关心这些,编译器会自动选择。

(3),变量

  • 在Kotlin中, 一切都是对象。所以,所有变量也都是对象(也就是说,任何变量都是根据引用类型来使用的)
  • Kotlin的变量分为 var (可变的) 和 val (不可变的)。
  • 尽量在Kotlin中首选使用val不变值,这样做的好处是可预测的行为和线程安全。

(4),包(package)
在Kotlin中也沿袭了Java的 package 这个概念,同时做了一些扩展。我们可以在一个包中引用另一个包

这里写图片描述
在student包中引用了teacher包,这里是可以编译通过的,调用Mark类的时候引用的也是teacher。可以看出Kotlin中我们可以修改包的引用,但是为了项目结构更加清晰一般我们不会这么做。

这里写图片描述

如果一个类类名比较长,调用时还可以起个别名。这里调用Mark类时,给Mark类起名为a,直接用a调用此类。

(5),区间
区间就是数学中的概念,开区间和闭区间。比如声明一个0到100的区间,区间也可以迭代。

 val intR:IntRange=0..100   //闭区间  [0,100]
 val  intR1:IntRange=0 until 100 // 前闭后开  [0,100)=[1,99]
 //循环输出区间中的值
 for(i in intR){
     println(i)
 }

(6),数组
数组和Java中的一样,我们看下如何定义数组。
创建数组有如下两种方式:

  • 使用arrayOf(),arrayOfNulls(),emptyArray()函数。
  • 使用Array(size:Int,init:(Int) -> T)构造器
//创建包含元素的数组(相当于Java数组的静态初始化)
val array:IntArray= intArrayOf(1,2,3,4,5)
val charArray:CharArray = charArrayOf('H','e','l','l','0')
val stringArray:Array<String> = arrayOf("你是","我的","眼")
//创建指定长度,元素为null的数组(相当于Java数组的动态初始化)
var douArray = arrayOfNulls<Double>(5)
var intArray = arrayOfNulls<Int>(5)
//创建长度为0的空数组
var strArray= emptyArray<String>()
//创建指定长度,使用Lambda表达式初始化数组元素
var array = Array(5, { (it * 2 + 97).toChar() }) 

println(array.size)   // 数组的长度
stringArray[1]="他"  //修改数组的值
println(array.slice(2..3))  //数组的截取
//数组遍历
for(i in array){
   println(i)
}

四,类和函数

(1),如何定义一个类,类的属性
①,类

class Student(name: String, sex: String, age: String)

定义类用class关键字,如果类中没有其他内容,可以省去大括号,并且这个类有一个默认的构造器

class Student(name: String, sex: String, age: String){
    init {
        //默认构造器函数
        println("学生:$name 性别 $sex 年龄 $age")
    }
}
//调用这个类
val s:Student= Student("张三","男","20")

init就是这个类默认的构造函数,类的调用不再需要new关键字。
②,属性

Java代码中定义一个属性,需要写它的set和get方法。Kotlin中默认有set和get方法

//Java代码
public class Student {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    } 
}
...
Student student=new Student();
student.setName("小明");
String name=student.getName();

//Kotlin代码

 class Student {
     var name: String = ""
 }
 ...
 val student=Student()
 student.name="小明"
 val name=student.name

我们也可以修改默认的方法,如果我们需要在set和get中访问自身的值,可以通过field这个预留字段来访问。

class Student {
    var name: String = ""
    get() = field.toUpperCase()
    set(value) {
        field="name=$name"
    }
}

(2),类的继承

class Student(name: String, sex: String, age: String):Course(name)
open class Course(name:String)
  • 学生类继承课程类,继承这里用 “:” 表示。我们可以发现用冒号的地方真多,变量的声明,类的继承,函数的返回值类型,都用到了 “:”进行表示。
  • 默认任何类都是继承Any,这里和Java中的(Object)类似。
  • 所有类默认是不可继承的,如果想继承需要用open或abstract关键字。
  • 当我们只有一个构造器时,需要从父类继承下来的构造器中指定需要的参数,这里用作替换Java中的super

(3),函数

①,这是一个main函数,函数可以用fun关键字来定义。

fun main(args: Array<String>) {
   println("Hello word")
}

这个函数没有返回值,如果没有指定函数的返回值,它返回就是Unit,和Java中的void类似。但是Unit也是一个对象。

②,我们也可以指定函数的返回值,这几种写法是一样的。如果返回的只是一个结果,那么可以省略大括号,直接等于返回值。也可以直接省略返回值类型。

//写法1
fun add(a: Int, b: Int): Int {
    return a + b
}

//写法2
fun add (a:Int,b:Int):Int=a+b

//写法3
fun add(a: Int, b: Int) {
    return a + b
}

//写法4
fun add (a:Int,b:Int)=a+b

④,我们也可以给函数的参数指定默认值,指定默认值的参数可以不传。注意:如果第一个参数有默认值,其他参数没有默认值,那么依然需要传入参数。与Java中方法的重载很类似的,Kotlin相当于把多个重载方法合并成了一个。

    //Kotlin代码
    fun student(name: String, sex: String = "男") {
        println("名字:$name 性别:$sex")
    }
    student("张三")
    student("小红", "女")
    
    //Java代码
     void student(String name, String sex) {
        System.out.println("name=" + name + ",sex=" + sex);
    }

    void student(String name) {
        System.out.println("name=" + name);
    }

(4),构造函数
构造函数分为两种:主构造函数和次构造函数

每个类默认都有不带参数的主构造函数,主构造函数没有函数体。如下在Student的主构造函数传入两个参数,由于主构造函数没有函数体,想在主构造函数中写逻辑可以在init中进行。次构造函数用constructor修饰

class Student(val no:String,val grade:Int) {
    init {
        
    }
}

(5),修饰符
Java中:public,private,protected,default
Kotlin中:public,private,protected,internal

其中private是一样的,public也是一样的,只不过在kotlin中是默认的。protected在Java中表示对当前类,子类和同一包路径下可见,在kotlin中只对当前类和子类可见。在kotlin中只对同一模块可见使用internal修饰。

(6),扩展函数
扩展函数就是可以在系统类的基础上扩展新的函数,比如:实现字符串相乘,扩展函数用operator关键字修饰。

operator fun String.times(n: Int): String {
    val builder = StringBuilder()
    repeat(n) {
        builder.append(this)
    }
    return builder.toString()
}

使用

  val str = "hello" * 3

五,表达式

(1),Lamdba表达式
①,Lambda表达式是一个匿名函数,将行为像数据一样传递,表达式使用"->“将参数和主体分开,”->"前面是参数部分,后面这是主体部分。Lambda表达式在Java8中引入的,具体用法这里不再讲解,读者可以阅读有关文章。这是一段Java代码,使用了Lambda表达式new一个线程。

  new Thread(new Runnable() {
             @Override
             public void run() {
                 System.out.println("lambda");
             }
         }).start();

   new Thread( () -> System.out.println("lambda") ).start();
  //这段代码可以看出,把一个内部类当成一个参数传入,代码简化了很多

②,再看下Kotlin代码如何使用Lambda表达式。

  //匿名函数
  val add=fun (a: Int, b: Int): Int {
        return a + b
  }
  //Lambda表达式写法
  val add={a:Int,b:Int->a+b}
 
  //Lambda表达式,没有"->"
  val student={
      println("我是学生")
  }

Lambda表达式和匿名函数类似。可以看到"->“前边是参数,”->“后边是返回值。当然”->"也不是必须的。就像这个学生函数,不需要参数,不需要返回值。
③,调用Lambda表达式,传入两个值,输出2。这里我们注意到,在调用Lambda时用到了小括号。

 println(add(1,1))

(2),分支表达式

在kotlin中if和else 可以是表达式,也可以是代码块

    //常规写法
    fun max1(a: Int, b: Int): Int {
        var num: Int
        if (a > b) {
            num = a
        } else {
            num = b
        }
        return num
    }

    //代码块写法,表达式可以是代码块
    fun max(a: Int, b: Int): Int {
        val num = if (a > b) {
            a
        } else {
            b
        }
        return num
    }

注:kotlin中没有三元表达式true? 1: 0 ,对应的写法 if(true) 1 else 0
(3),when表达式
when表达式和switch类似,在kotlin中没有switch,替代它的是when表达式。else就相当于switch中的default

    val x = -1
    when (x) {
        is Int -> print("is Int")
        -1, 0 -> print("x == 0")   // 同时满足-1和0的条件,相当于switch中去掉break
        1 -> print("x == 1")
        2 -> print("x == 2")
        else -> {
            print("")  // 不是上述条件  相当于switch中的default
        }
    }

(4),while表达式
while循环和do while循环和Java一样

       var count = 0
        //当count小于8时,执行循环体
        while (count < 8) {
            print("count:${count}")
            count++
        }

(5),for-in表达式
for-in循环,用于数组,集合,字典的遍历,for-in循环无需声明常量。break可以终止循环和Java一样,另外break也可以终止外层循环,这就需要break后边要跟一个标签。如示例2其中jump@就是标签,在外层循环体外声明jump@标签,break被指定终止循环的标签,这样就可以终止外层循环。

  //示例1
  for (i in 0 until 10){
            print("i=${i}")
           if(i==4){
                break
            }
        }

  //示例2
   jump@ for (i in 0 until 10) {
            //内层循环
            for (j in 0 until 5) {
                if (j == 3) {
                    break@jump
                }
            }
        }

continue和Java一样,可以忽略循环中剩下的语句,如示例1。另外和break类似,continue也可以声明标签,如示例2,j的值永远超不过4,当j等于4时continue@jump结束了外层循环的当次循环。

 //示例1
 for(i in 0 until 10){
            print("打印 i=${i}")
            if(i==4){
                //忽略剩下的语句
                continue
            }
            print("continue i=${i}")
        }
   //示例2
   jump@ for(i in 0 until 10){
            for(j in 0 until 10) {
                print("打印 i=${i} j=${j}")
                if (j == 4) {
                    //忽略剩下的语句
                    continue@jump
                }
            }
        }

下一篇:kotlin进阶

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值