Kotlin笔记--基础

 1 函数和变量
      函数构成:函数名称,参数列表,返回类型,函数体;函数的声明以关键字fun开始,函数名称 紧随其后,接下来是括号括起来的 参数列表,参数列表的后面跟着 
   返回类型,返回类型和参数列表之间用冒号隔开,最后是函数体。如下:

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

2 表达式和语句
    上面的栗子 if是 表达式,而不是语句,区别:  表达式 有值,并且能作为另一个表达式的一部分使用。语句 总是包含着它的代码块中的顶层元素,并且没有自己的值。
      在Java中,所有的控制结构都是语句,而在Kotlin中,除了for、do和do/while以外大多数控制结构都是表达式。当函数体是由单个表达式构成时,可以用这个表达式作为完整的函数体,并且去掉花括号和return语句,上面的例子就是这种情况,因此可以改写为:

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

如果函数体写在花括号中,我们说这个函数有 代码块体, 如果它直接返回了一个表达式,它就有 表达式体

3 省略返回类型
      对于 表达式体函数,可以省略返回类型,因为编译器会分析作为函数体的表达式,并把它的类型作为函数的返回类型,这种分析称为 类型推导。但是对于有返回值的 代码块体函数,必须显示地写出返回类型和return语句。上面栗子可以简化:

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

4 变量
  在Kotlin中,变量的声明以关键字val/var开始,然后是变量名称,最后可以加上类型(不加也可以),这里分为两种情况:

    如果指定了初始化器,那么在不指定类型的情况下,编译器会分析初始化器表达式的值,并把它的类型作为变量的类型,例如下面两个就分别为Int和Double类型:

 fun valFunc() {
	   val dValue = 1e2
	   val iValue  = 6
	   println("dValue = $dValue,iValue=$iValue")
	 }

如果没有指定初始化器,需要显示指定它的类型,因为此时编译器无法推断出它的类型。

5 可变变量和不可变变量 
    5.1 不可变引用 val 使用val声明的变量不能在初始化之后再次赋值,它对应的是Java的final变量。默认情况下,应该尽可能地使用val关键字来声明所有的Kotlin变量。在定义了val变量的代码块执行期间,val变量只能进行唯一一次初始化,但是,如果编译器能确保唯一一条初始化语句会被执行,可以根据条件使用不同的值来初始化它。
    5.2 可变引用 var 这种变量的值可以改变,但是它的类型却是改变不了的。如果需要在变量中存储不匹配类型的值,必须手动把值转换或强制转换到正确的类型。

    5.3 字符串模板
    Kotlin可以在字符串字面值中引用局部变量,只需要在变量名称前面加上字符$.

栗子:
	fun main(args: Array<String>) {
    val name = if (args.size > 0) args[0] else "Kotlin"
    println("Hello, $name!")
}

     如果要在字符串中使用$,需要对它进行转义 \$(转义)$name 除了可以引用 局部变量之外 ,还可以引用更加复杂的表达式,只需要把表达式用花括号扩起来。

 fun main(args: Array<String>) {
    println("Hello, ${if (args.size > 0) args[0] else "someone"}!")
  }

6 类
     6.1 属性  类的概念就是把数据和处理数据的代码封装成一个单一的实体,在Java中,数据存储在字段中,并且通常是私有的。如果想让类的使用者访问到数据得提供访问方法,即getter/setter。在Java中,字段和其访问器的组合常常被叫作属性。在Kotlin中,属性是头等的语言特性,完全 替代了字段和访问器方法。在类中声明一个属性和声明一个变量一样:使用val/var关键字,前者是只读的,而后者是可变的。

       当声明属性的时候,就声明了对应的访问器(只读属性有一个gettter,而可变属性则有getter/setter),例如下面的例子,声明了只读的name属性,可变的isMarried属性,其赋值和读取的方法如下所示:

class Person(
    val name: String,
    var isMarried: Boolean
)

fun main(args: Array<String>) {
    val person = Person("Bob", true)
    println(person.name)
    println(person.isMarried)
	person.isMarried = false
	println(person.isMarried)
}

输出:
Bob
true
false

 6.2 自定义访问器
     假设声明一个矩形,它能判断自己是否是正方形,那么就不需要一个单独的字段来存储这个信息,此时我们可以写一个自定义的访问器:用val开头作为声明,紧跟着的是属性的名称和类型,接下来是get()关键字,最后是一个函数体。

栗子:
	class Rectangle(val height: Int, val width: Int) {
    val isSquare: Boolean
        get() {
            return height == width
        }
   }

fun main(args: Array<String>) {
    val rectangle = Rectangle(60, 63)
    println(rectangle.isSquare)
}
   输出: false

 6.3 目录和包
     Kotlin中包的概念和Java类似,每个kotlin文件都能以一个package语句开头,而文件中定义的所有声明(类、函数及属性)都会被放到这个包中。  如果其他文件定义的声明也有相同的包,这个文件可以直接使用它们;如果包不同,则需要导入它们,导入语句放在文件的最前面并使用import关键字kotlin不区分导入的是类还是函数,而且,它允许使用import关键字导入任何种类的声明,可以直接导入顶层函数的名称,也可以在包名称后加上.*来导入特定包中定义的所有声明。在Java中,要把类放到和包结构相匹配的文件与目录结构中,而在kotlin中,可以把多个package声明不相同的类放在同一个文件夹中。

 6.4 表示和处理选择: 枚举和when
       声明枚举类时,enum是一个所谓的软关键字,只有当它出现在class前面时才有特殊的意义,在其他地方可以当做普通名称使用。 而class仍然是一个关键字,下面是一个枚举类的声明:

enum class Color {
    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
  }
     带属性的枚举类:
	  enum class Color(
        val r: Int, val g: Int, val b: Int
) {
    RED(255, 0, 0), ORANGE(255, 165, 0),
    YELLOW(255, 255, 0), GREEN(0, 255, 0), BLUE(0, 0, 255),
    INDIGO(75, 0, 130), VIOLET(238, 130, 238);

    fun rgb() = (r * 256 + g) * 256 + b
}

      说明:当声明一个带属性的枚举类时,有几点需要注意:当声明每个枚举常量的时候,必须提供该常量的属性值。如果要在枚举类中定义任何方法,就要使用分号把枚举常量列表和方法分开。

6.5 使用“when”处理枚举类
     when是一个有返回值的表达式,因此,作为表达式函数体,它可以去掉花括号和return语句,并省略返回类型的声明。下面是一个通过when 处理枚举类的栗子,它和Java中的switch语句类似,根据when中Color的值走到对应的分支,除此之外,我们可以把多个值用逗号间隔,合并到同一个分支:

 enum class Color {
    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
}

fun getMnemonic(color: Color) =
    when (color) {
        Color.RED -> "Richard"
        Color.ORANGE -> "Of"
        Color.YELLOW -> "York"
        Color.GREEN -> "Gave"
        Color.BLUE -> "Battle"
        Color.INDIGO -> "In"
        Color.VIOLET -> "Vain"
    }

fun main(args: Array<String>) {
    println(getMnemonic(Color.BLUE))
}

 输出:Battle

 6.6 智能转换:合并类型检查和转换
     在kotlin中,判断一个变量是否是某种类型需要使用is关键字,它和Java当中的instanceOf相似。 在Java中,在检查完后还需要显示地加上类型转换。在kotlin中,如果你检查过一个变量是某种类型,后面就不需要再转换它,可以把它当做你检查过的类型来使用。 我们用下面这个例子,Num和Sum都实现了Expr接口,通过is判断它的类型,完成递归求和。可以看到,在is判断之后,不再需要转换成Num或Sum,就可以直接访问该类的成员变量。

interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr

fun eval(e: Expr): Int {
    if (e is Num) {
        val n = e as Num
        return n.value
    }
    if (e is Sum) {
        return eval(e.right) + eval(e.left)
    }
    throw IllegalArgumentException("Unknown expression")
}

fun main(args: Array<String>) {
    println(eval(Sum(Sum(Num(1), Num(2)), Num(4))))
}

  输出: 7

重构:用“when” 代替 “if”

interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr

fun eval(e: Expr): Int =
    when (e) {
        is Num ->
            e.value
        is Sum ->
            eval(e.right) + eval(e.left)
        else ->
            throw IllegalArgumentException("Unknown expression")
    }

fun main(args: Array<String>) {
    println(eval(Sum(Num(1), Num(2))))
} 

输出: 3 

7 迭代事物“while” 循环 和"for" 循环
  7.1 while循环
      kotlin和Java一样,有while循环和do-while循环,它们的语法和Java中相应的循环完全一致。
  7.2 迭代数字:区间和数列
     在Java当中,对于循环的处理方式为:先初始化变量,在循环的每一步更新它的值,并在值满足某个限制条件时退出循环。 而在Kotlin中,为了替代常见的循环用法,使用了 区间 的概念,其本质上就是两个值之间的间隔,这两个值通常是数字: 一个起始值,一个结束值。使用..运算符来表示区间,而结束值始终是区间的一部分。 

如下:
    for (c in 'A'..'F') {
        val binary = Integer.toBinaryString(c.toInt())
        binaryReps[c] = binary
    }

    7.3 迭代map  更新map,用的是TreeMap,在更新map时,我么可以像使用数组一样,只不过下标变成key值:

val binaryReps = TreeMap<Char, String>()

    for (c in 'A'..'F') {
        val binary = Integer.toBinaryString(c.toInt())
        binaryReps[c] = binary
    }

7.4 使用"in"检查集合 和区间的成员
      使用in运算符来检查一个值是否在区间中,或者它的逆运算!in来检查这个值是否不在区间中,区间不仅限于字符,假如有一个支持实例比较操作的任意类(实现了java.lang.Comparable接口),就能创建这种类型的对象的区间。

 fun fizzBuzz(i: Int) = when {
    i % 15 == 0 -> "FizzBuzz "
    i % 3 == 0 -> "Fizz "
    i % 5 == 0 -> "Buzz "
    else -> "$i "
}

fun main(args: Array<String>) {
    for (i in 1..100) {
        print(fizzBuzz(i))
    }
}

 8 异常
       kotlin的异常处理和Java以及其他许多语言的处理方式类似:一个函数可以正常结束,也可以在出现错误的情况下抛出异常。
方法的调用者能捕获到这个异常并处理它;如果没有处理,异常会沿着调用栈再次抛出。抛出异常时使用throw关键字,但是不必使用new关键字来创建异常实例。 throw结构是一个表达式,能作为另一个表达式的一部分使用。

import java.io.BufferedReader
import java.io.StringReader

fun readNumber(reader: BufferedReader): Int? {
    try {
        val line = reader.readLine()
        return Integer.parseInt(line)
    }
    catch (e: NumberFormatException) {
        return null
    }
    finally {
        reader.close()
    }
}

fun main(args: Array<String>) {
    val reader = BufferedReader(StringReader("239"))
    println(readNumber(reader))
}


和Java最大区别就是throws子句没有出现在代码中

8.2 “try”作为表达式
       kotlin中的try关键字就像if和when一样,引入了一个表达式,可以把它的值赋给一个变量,并且需要用花括号把语句主体括起来。如果主体包含多个表达式,那么整个try表达式的值就是最后一个表达式的值。

import java.io.BufferedReader
import java.io.StringReader

fun readNumber(reader: BufferedReader) {
    val number = try {
        Integer.parseInt(reader.readLine())
    } catch (e: NumberFormatException) {
        return
    }
    println(number)
}

fun main(args: Array<String>) {
    val reader = BufferedReader(StringReader("not a number"))
    readNumber(reader)
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值