Kotlin基础

Kotlin基础

内容包括

  • 声明函数、变量、类、枚举以及属性
  • Kotlin中的控制结构
  • 智能转换
  • 抛出和处理异常

2.1基本要素:函数和变量

2.1.1 Hello ,word

fun main(args: Array<String>) {
    println("hello world")
}
  • 关键字fun用来声明一个函数。
  • 参数类型写在它的名称后面。
  • 函数可以定义在文件的外层,不需要把它放在类中。
  • 数组就是类。和java不同,Kotlin没有声明数组类型的特殊语法。
  • 使用println代替了System.out.println。
  • 和许多其他现代语法一样,可以省略每行代码后面的分号

2.1.2 函数

fun main(args: Array<String>) {
    println(max(3,4))
}

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

在Kotlin中,if是表达式,而不是语句。

语句和表达式的区别在于,表达式有值,并且能作为另一个表达式的一部分使用;而语句总是包围着代码块的顶层元素,并且没有自己的值。

表达式函数体
可以让上面的函数变得更简单。

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

或者

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

注意只有表达式体函数的返回类型可以省略

2.1.3 变量

val question="adsflsjdfl"
val answer1 = 42
// 显示的指定变量类型
val answer2: Int = 42 

如果变量没有初始化,需要显示地指定它的类型:

val answer2: Int
answer2 = 42

可变变量和不可变变量
声明变量的关键字有两个:

  • val 使用val声明的变量不能在初始化之后再次赋值。它对应的Java的final变量。
  • var 这种变量的值可以被改变。这种声明对应的是普通(非final)的Java变量。

默认情况下,应该尽可能地使用val关键字来声明所有的Kotlin变量。

在定义了val变量的代码块期间,val变量只能进行唯一一次初始化,如果编译器能确保只有唯一一天初始化语句会被执行

val message: String
if(1<0){
    message="www"
}else{
    message="qqq"
}
println(message)

注意,尽管val引用自身是不可变的,但是它指向的对象可能是可变的。例如

val languages = arrayListOf("Java")
languages.add("Kotlin")
println(languages)

2.1.4 更简单的字符串格式化:字符串模板

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

这个例子介绍了一个新特性,字符串模板。

如果要在字符串中使用$符号需要对它进行转义:

println("\$x")

还可以引用更复杂的表达式,而不是仅限于简单的变量名称,只需要把表达式用花括号括起来:

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

2.2 类和属性

Java代码

public class Person {
    private final String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

转换成Kotlin代码

class Person(val name: String)

只有数据没有其它代码通常被叫做值对象

2.2.1 属性

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

name:是只读属性生成一个字段和一个getter方法
isMarried:可写属性,一个字段、一个getter和一个setter

2.2.2 自定义访问器

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

每次获取isSquare值的时候都会调用泳get(){…}返回计算后的属性值

2.2.3 Kotlin源码布局:目录和包

Kotlin可以用关键字导入类和函数
Kotlin中包名可以和文件名不同

2.3 表示和处理选择:枚举和“when”

2.3.1 声明枚举类

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

Kotlin中,enum是一个软关键字:只有当它出现在class前面时才有特殊的意义,在其他的地方可以把它当做普通的名称使用

可以给枚举类声明属性和方法

print(Color.ORANGE.rgb())

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
}

如果要在枚举类中定义任何方法,就要使用分号把枚举常量列表和方法分开

2.3.2 使用“when”处理枚举类

fun getMnemonic(color: Color) =
        when (color) {
            Color.BLUE -> "blue"
            Color.GREEN -> "green"
            else -> "other"
        }

和if相似when是一个有返回值的表达式

fun getMnemonic(color: Color) =
        when (color) {
            Color.BLUE, Color.RED -> "blue"
            Color.GREEN -> "green"
            else -> "other"
        }

如果多个条件的返回值相同,可以把多个值合并到同一个分支,只需要用逗号隔开。

2.3.3 在“when”结构中使用任意对象

Kotlin中的when结构比Java中的switch强大的多。switch要求必须使用常量(枚举常量、字符串或者数字字面值)作为分支条件,和它不一样when允许使用任何对象。

fun mix(c1: Color, c2: Color) =
        when (setOf(c1, c2)) {
            setOf(Color.RED, Color.ORANGE) -> Color.RED
            setOf(Color.GREEN, Color.INDIGO) -> Color.GREEN
            else -> throw Exception("color error")
        }

2.3.4 使用不带参数的“when”

2.3.3中的例子每次调用的时候会创建多个Set实例,频繁调用效率低下

fun mixOptimized(c1: Color, c2: Color) =
        when {
            c1 == Color.RED && c2 == Color.ORANGE || c2 == Color.RED && c1 == Color.ORANGE -> Color.RED
            c1 == Color.GREEN && c2 == Color.INDIGO || c2 == Color.GREEN && c1 == Color.INDIGO -> Color.RED
            else -> throw Exception("color error")
        }

性能优化了但是影响了可读性

2.3.5 只能转换:合并类型检查和转换

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) {
            e.value
        } else if (e is Sum) {
            eval(e.left) + eval(e.right)
        } else {
            throw IllegalArgumentException("unknown expression")
        }
        
println(eval(Sum(Sum(Num(1), Num(2)), Num(4)))) 

在Kotlin中通过is判断一个变量是否是某种类型
如果通过is检测过一个变量是某种类型,后面就不需要转换他实际上编译器为你执行了类型转换,我们把这种行为称为智能转换

使用as关键字来表示到特定类型的显式转换
val n = e as Num

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

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

2.3.7 代码块作为“if”和“when”的分支

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

2.4 迭代事物:“while”循环和“for”循环

2.4.1 “while”循环

Kotlin 有while循环和do-while循环,他们的语法和Java中相应的循环没有什么区别:

while(condition){
    /*...*/
}

do{
    /*...*/
} while(condition)

2.4.2 迭代数字:区间和数列

区间本质上就是两个值之间的间隔,这两个值通常是数字:一个起始值,一个结束值。使用…运算符来表示区间:

val oneToTen = 1..10

Kotlin的区间是包含的或者闭合的,两边的值是区间的一部分

一个FizzBuzz小游戏

for(i in 1..100){
    println(fizzBuzz(i))
}
    
fun fizzBuzz(i: Int) = when {
    i % 15 == 0 -> "fizzBuzz "
    i % 3 == 0 -> "fizz"
    i % 5 == 0 -> "buzz"
    else -> "$i"
}

in 、downTo、step和until

  • in 可以迭代区间和集合
  • downTo 递减
  • step 跳过几个
  • until 不包含连段的例如(1 until 100 不包含1和100)

2.4.3 迭代map

val binaryReps = TreeMap<Char,String>()
for (c in 'A'..'F'){
    val binary = Integer.toBinaryString(c.toInt())
    binaryReps[c]=binary
}

for ((letter,binary) in binaryReps){
    println("$letter = $binary")
}

可以迭代的时候跟踪下标

val list = arrayListOf<String>("10","11","1001")
    for ((inde,valu) in list.withIndex()){
        println("$inde:$valu")
    }

2.4.4 使用“in” 检查集合和区间的成员

使用in运符来检查一个值是否在区间中,或者它的逆运算,!in,来检测这个值是否不在区间中。下面展示了如何使用in来检测一个字符是否属于一个字符区间。

fun isLetter(c:Char) = c in 'a'..'z' || c in 'A'..'Z'
fun isNotDigit(c:Char) = c !in '0'..'9'

in运算符和!in运算符也适用于when表达式

fun recognize(c: Char) = when (c) {
    in '0'..'9' -> "it is a digit"
    in 'a'..'z', in 'A'..'Z' -> "It is a letter"
    else -> "I do not know ..."
}

2.5 Kotlin中的异常

2.5.1 “try”"catch"和“finally”

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

2.5.2 "try"作为表达式

rreadNumber(BufferedReader(StringReader("asd")))

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

2.6小结

  • fun关键字用来声明函数。val关键字分别用来声明只读变量和可变变量
  • 字符串模板帮助你避免烦琐的字符串连接。在变量名称前加上 前 缀 或 者 用 前缀或者用 { }包围一个表达式,来把值注入到字符串中。
  • 值对象类在Kotlin中以简洁的方式表示。
  • 熟悉的if现在是带返回值的表达式。
  • when表达式类似于Java中的switch但功能强大。
  • 在检查过变量具有某种类型之后不必显示地转换它的类型:编译器使用智能转换帮你自动的完成。
  • for、while和do-while循环与Java类似,但是for循环现在更加方便,特别是当你需要迭代map的时候,又或是迭代集合需要下标的时候。
  • 简洁的语法1…5会创建一个区间。区间和数列允许Kotlin在for循环中使用统一的语法和同一套抽象机制,并且还可以使用in运算符和!in运算符来检查值是否属于某个区间。
  • Kotlin中的异常处理和Java非常相似,除了Kotlin不要求你声明函数可以抛出的异常。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值