Kotlin之基础语法

Kotlin之基础语法

语言简介

kotlin是一门新语言,它有自己的编译器,能将kotlin代码编译成class文件,因此能被JVM识别,所以kotlin也是一门解释型语言,同java一样。JVM并不关心class文件来自于Java还是Kotlin,只要是符合规定的class文件,它都能识别。

语法特点

  • Kotlin每一行代码的结尾是不用加分号的。
  • Kotlin完全抛弃了Java中的基本类型,继而全部使用对象数据类型。
  • Kotlin主要有类(class)、文件(file)、接口(interface)、密封接口(sealed interface)、数据类(data class)、枚举类(enum class)、密封类(sealed class)、注解(annotation)、单例类(object)。
    • File通常是用于编写Kotlin顶层函数和扩展函数的。

常用的关键字

  • is关键字:可以用来判断对象的类型,相当于java的instanceof。
    •   val a = 10
        val b = a is Int
      
  • Unit
    • 也是一种类型,就像Int一样,只是它不代表任何信息。
    • 它的实例只有一个,可写为()。
  • ?:
    • 它叫做Elvis运算符,或者null合并运算符。
    • 作用:可以用来给可空类型的变量指定为空情况下的值。
      •  var test: Int? = null
         test = test ?: 1
        
  • ?.
    • 对象方法调用,如果对象为空,则不进行任何操作;否则则调用该方法。
      •  val dog: Dog? = null
         dog?.test()
        
  • ?:
    • 如果对象为空,则运行右侧;否则运行左侧。
      •  val a: Int? = null
         val b = a ?: 0
        
  • !!
    • 非空断言,放在一个变量后面断定该变量不可能为空。如果变量为空了就会报错。
    • 实际写代码时建议不要用,除非万不得已。
      •  val a: Int? = null
         val b = a!! == 2
        
  • as关键字
    • 可以进行强转。
    • 可以用来给包起别名。如果包名出现命名冲突,可以用来消除歧义。
      •  import com.google.gson.Gson as MyGson
        

变量

  • 声明变量:使用var和val。
    • val:不可变变量。等同于Java的final变量。
      • 好的习惯:除非一个变量明确允许被修改,否则就应该把定义为final的。因此,建议永远优先使用val来声明一个变量,当val不满足需求时再使用var。
      •   val s: String = "hello"
        
    • var:可变变量。
      •  var s: String
        
    • getter和setter:当你在声明一个类的属性时,编译器会自动生成对应的getter、setter方法,但是你也可以主动声明这两个方法来实现一些特殊的逻辑。
      • val属性只有getter方法,而var变量可以有getter和setter方法。
      • private属性会自动省略getter和setter方法。
        •  val Context.`package`: String
           	get() = this.packageName
          
  • 可空类型:
    • 在类型之后加一个问号?,表示该变量可以为空。
      •  val name: String? = null
        
  • 出色的类型推导:编译器可以在不显式声明类型的情况下,自动推导出它所需要的类型。
    • 虽然Kotlin的类型推导机制很强大,但是也有它推导不了的情况,比如对一个变量延迟初始化,这时就无法推导,必须在定义时显式地声明变量类型才可以。
    •  val s = "hello"
       println("s的类型是:${s.javaClass.name}")
       
       输出:
       s的类型是:java.lang.String
      
  • 声明函数返回值类型:
    • 如果没有声明返回的类型,函数会默认返回Unit类型。
    •  fun sum(x: Int, y: Int): Int {
       	return x + y
       }
      
    • 以上代码可以用表达式函数体来优化。
      • 表达式函数体:用单行表达式与等号的语法来定义函数。
      • 与之对应,普通的函数声明则可叫做代码块函数体。
      •  fun sum(x: Int, y: Int) = x + y
        
      • 在使用表达式函数体可以不声明返回值类型。但这不代表只要使用了表达式函数体就可以不声明返回值类型。
        • 如下,编译器不能针对递归函数的情况推导类型。
        •  fun foo(n: Int): Int = if (n == 0) 1 else n * foo(n - 1)
          
    • 总结:哪些情况需要显式声明类型?
      • ①它是函数的参数:必须。
      • ②它是一个非表达式定义的函数:除了返回Unit,其他情况必须。
      • ③它是一个递归的函数:必须。
      • ④它是一个公有方法的返回值:为了代码可读性和输出类型的可控性,建议。
      • ⑤除了以上情况,就可以不显式声明,除非碰到意外。

函数

  • 函数-function,方法-method,它们是同一个东西,只是叫法习惯不同。在c、c++中习惯叫做函数,在Java中习惯叫做方法,而在Kotlin中习惯叫做函数。
  • 定义:使用fun关键字来定义函数。
  • 格式:
    •  fun methodName(param1: Int, param2: Int): Int {
       
       }
      
  • 函数默认参数值:
    •  fun test(num: String = "wangwang", age: Int = 10) {
       	println("name  = $name, age = $age")
       }
      

函数可变参数

  • 使用varargs关键字来定义。
  • 类似于Java的“…”,不同的是Java的可变参数必须是最后一个参数,而kotlin没有这个限制。
  • 它们都可以在函数体中意数组的方式来使用可变参数变量。
    •  fun test(vararg nums: Int, count: Int) {
               nums.forEach { println(it) }
       }
      
       test(1, 2, 3, count = 4)
       
       输出:
       1
       2
       3
      
  • 可以使用星号*来传入外部的变量作为可变参数的变量。
    •  val arr = IntArray(3)
       test(*arr, count = 3)
       
       输出:
       0
       0
       0
      

逻辑控制

if表达式

  • kotlin的if语句与Java不同的是它可以有返回值。
  •  val random = Random(47)
     val a = random.nextInt(100) + 1
     val b = random.nextInt(100) + 1
     val num = if (a > b) a else b
     println("a = $a, b = $b, num = $num")
     
     输出:
     a = 97, b = 59, num = 97
    

when表达式

  • when表达式类似于switch语句,有when关键字开始,用大括号包含多个逻辑分支,每个分支用“->”连接,不需要break,从上到下匹配,一直匹配完为止,否则执行else分支的逻辑,else分支类似于default。
  • 对比Java的switch语句,switch只能使用整型、短于整型或字符串的变量。
  • when表达式同样可以有返回值。
    •  val random = Random(47)
       val a = random.nextInt(100) + 1;
       val b = when(a) {
               100 -> "完美"
               60 -> "及格"
               else -> "不及格"
       }
      
  • 每个分支都有返回值,最终返回值的类型是所有分支相同的返回类型,或者公共类型。
    • 分支如果只有一行代码,可以省略{}。
    •  fun b(a: Int) = when(a) {
               100 -> "完美"
               60 -> "及格"
               else -> "不及格"
       }
      
  • when关键字的参数可以省略。
    •  fun b(a: Int) = when {
               a == 100 -> "完美"
               a == 60 -> "及格"
               else -> "不及格"
       }
      
  • 表达式可以组合。
    •  fun b(is100: Boolean, a: Int) = when {
               is100-> "完美"
               a == 60 -> "及格"
               else -> "不及格"
       }
      

for循环

  • kotlin中的while和do-while与Java中的一样。
  • kotlin的for循环,可以声明i的类型:
    •  for (i: Int in 1..5) {
               println(i)
       }
       
       输出:
       1
       2
       3
       4
       5
      
  • 范围表达式:
    • Range表达式是通过rangeTo函数实现的,通过“..”操作符与某种类型的对象组成,左闭右闭,[0, 10]。除了整数的基本类型之外,该类型需实现java.lang.Comparable接口。
      • 当对整数进行for循环时,还可以使用step函数来定义步长。
        •  for (i: Int in 1..5 step 2) {
           	println(i)
           }
           
           输出:
           1
           3
           5
          
      • 倒序:使用downTo方法实现。
        •  for (i: Int in 5 downTo 1 step 2) {
           	println(i)
           }
           
           输出:
           5
           3
           1
          
      • 半开区间:左闭右开,[0,10),使用until函数。
        •  for (i in 1 until 5) {
           	println(i)
           }
           
           输出:
           1
           2
           3
           4
          
      • 打印字符a-z:
        •  for (i in 'a'..'z') {
           	println(i)
           }
          
  • 用“in”来检查成员关系
    • 用来检查一个元素是否是一个区间或集合中的成员。
      •   val isIn = "a" in listOf("a", "b", "c")
          println("a是否在列表中:$isIn")
        
          输出:
          a是否在列表中:true
        
    • 在in前加上“!
      •  val isIn = 1 !in listOf(1, 2, 3)
         println("1不在列表中:$isIn")
         
         输出:
         1不在列表中:false
        
    •  val isIn = "kot" in "abc".."xyz"
       println("isIn = $isIn")
       
       输出:
       isIn = true
      
    • 任何提供迭代器(iterator)的结构都可以用for语句进行迭代。
    • 还可以通过调用一个withIndex方法提供一个键值元组。
      •  for ((index, value) in arrayOf(100, 28, 73).withIndex()) {
             println("当前元素为:$value, 下标为:$index")
         }
         
         输出:
         当前元素为:100, 下标为:0
         当前元素为:28, 下标为:1
         当前元素为:73, 下标为:2
        
  • 中缀表达式:
    • 如in step downTo until等方法都不是用点进行调用的,而是使用中缀表达式来调用。
    • 如to方法,他可以返回一个Pair:
      • public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
      • to这种形式定义的函数被称为中缀函数
        • 由于to会返回Pair这种键值对的数据结构,因此常与map一起使用。
      • 使用:
        • A 中缀方法 B
      • 定义一个中缀函数必须满足:
        • ①该中缀函数必须是某个类型的扩展函数或成员方法。
        • ②该中缀函数只能有一个参数。
        • ③中缀函数的参数不能有你·默认值。
        • ④该参数不能是可变参数。
      • 自定义中缀函数:
        • 中缀函数除了可以使用中缀表达式那样调用,也可以像正常函数那样调用。
        •   class Dog {
            	infix fun show(name: String) {
            		println("name is $name")
            	}
            }
            
            //调用:
            val dog = Dog()
            dog show "wangwang"
            
            输出:
            name is wangwang
          

方法和成员引用

  • Kotlin的一种特殊语法:使用双冒号“::”对某个类的方法进行引用。
    • Dog类:我们定义了一个Dog类,调用时我们把常规的写法和双冒号的写法做了对比,实践发现爽冒号可以对类的构造方法、成员变量和成员方法创建引用变量,并通过该变量可以创建了Dog实例、调用dog实例的属性以及调用dog实例的方法。
      •  class Dog(val name: String) {
        
         	fun run() {
             	println("$name start run!")
         	}
         }
         
         //调用:
         fun main() {
         	//①正常语法编写:
         	val dog1 = Dog("lala")
         	println("Dog1's name is ${dog1.name}.")
         	dog1.run()
        
         	//②双冒号语法编写:
         	//引用类的构造方法
         	val getDog = ::Dog
         	val dog2 = getDog("wangwang")
         	//引用类的成员变量
         	val getName = Dog::name
         	val name = getName(dog2)
         	println("Dog2's name is $name.")
         	//引用类的成员方法
         	val execRun = Dog::run
         	execRun(dog2)
         }
         
         输出:
         Dog1's name is lala.
         lala start run!
         Dog2's name is wangwang.
         wangwang start run!
        
  • 通过狗狗名称长度进行过滤:
    •  fun filterDogs(dogs: List<Dog>, filter: (Dog) -> Boolean): List<Dog> {
       	val res = mutableListOf<Dog>()
       	for (dog in dogs) {
               if (filter(dog)) {
                       res.add(dog)
               }
       	}
       	return res
       }
       
       class Dog(val name: String) {
       	fun filterName(dog: Dog): Boolean {
               return dog.name.length > 4;
       	}
       }
       
       val dogs = arrayListOf(Dog("lala"), Dog("wangwang"), Dog("gaga"))
       println("规则:名字长度小于等于4的将被过滤。\n过滤前:")
       dogs.forEach { println(it.name) }
      
       //调用:
       val filterDogs = filterDogs(dogs, Dog("")::filterName)
       println("过滤后:")
       filterDogs.forEach { println(it.name) }
       
       输出:
       规则:名字长度小于等于4的将被过滤。
       过滤前:
       lala
       wangwang
       gaga
       过滤后:
       wangwang
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值