Kotlin基础
1. 函数
- 1 . 示例
fun max(a: Int,b: Int): Int{
return if (a>b) a else b
}
println(max(1,2))
/**
* Main方法
*/
fun main(args: Array){
println("Hello World")
}
- 2 . 语句与表达式:在Kotlin中if是表达式,不是语句,在Kotlin中除了循环(for/do/do...while)外,大多数控制结构都是表达式
- 3 . 如果函数体写在花括号中,我们说这个函数有代码块体。如果它直接返回一个表达式,它就有表达式体。只有表达式体函数的返回类型可以省略。
- 4 . 一个函数要么具有并不是代码块的表达式函数体,要么具有包含显示return语句的代码块函数体
IDEA中提供这两种函数风格之间转换的操作
2. 变量
-
1 . 可变变量和不可变变量
-
val
:不可变引用(final) -
var
:可变引用 - 若变量没有初始化,则需要显示的指定他的类型
- 不可变变量,只能进行唯一一次初始化
-
val
引用自身是不可变的,但是它指向的对象可能是可变的 -
var
允许变量改变自己的值,但他的类型却是不可变的
-
val a = "string"
val a: String = "string"
3. 字符串格式化
- 1 . 示例
fun main (args: Array){
val name = if (args.size>0) args[0] else "kotlin"
/**
* 引用变量,若要打印$符号,则需要转义操作 \$
*/
println("Hello $name")
/**
* 引用表达式
*/
if(args.size>0){
println("Hello ,${args[0]}")
}
/**
* 双引号中使用双引号,需要保证内部的双引号在表达式体内
*/
println("Hello , ${if (args.size>0) args[0] else "kotlin"}")
}
- 2 . 编译后的代码,创建了一个StringBulider对象,并吧常量部分和变量附加上去
4. 类和属性
- 1 . 类
class Person(val name: String)
kotlin 中public是默认的可见性,所以省略了
-
2 . 属性
- 声明为
val
的属性是只读的,并自动提供一个getter - 声明为
var
的属性是可变的,并自动提供一个getter和一个setter - 对于Java中定义的类,一样可以使用Kotlin语法进行属性访问
class Person( val name: String var isMarried: Boolean ) val person = new Person("Bob",true) println(person.name)
- 声明为
-
3 . 自定义访问器
- 此方式和声明一个没有参数的函数一样的效果
- 在Java中访问该属性,直接调用
isSquare()
即可 - 不需要使用带花括号的完成语法
- 通常来说,若描述的是类的属性(特征),则应该声明为属性
class Rectangle(val height: Int, val width: Int) { val isSquare: Boolean get() { return height == width } /** * 也可以为: * get() = height==width */ } fun main(args: Array
) { val rectangle = Rectangle(41, 43) println(rectangle.isSquare) } -
4 . 枚举
- Kotlin中,只有
enum
关键字在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 } fun main(args: Array
) { println(Color.BLUE.rgb()) } - Kotlin中,只有
-
5 . 接口与实现
- 声明实现类时,使用一个冒号(
:
)后面跟上接口名称,来标记这个类实现了这个接口
/** * 接口,标记接口,无任何方法 */ interface Expr /** * 实现类,使用:来标明实现哪个接口 */ class Num(val value: Int) : Expr /** * 实现类,使用:来标明实现哪个接口 */ class Sum(val left: Expr, val right: Expr) : Expr
- 声明实现类时,使用一个冒号(
-
6 . 类型检查和类型转换
- 使用
is
来判断一个变量是否是某种类型,在进行类型判断后,变量会自动转换成响应的类型,无需强制转换,这种方式的转换为智能转换,在使用智能转换时,属性值必须是val
属性,而且不能有自定义的访问器 - 使用
as
来显示转换,val n = e as Num
- 使用
5. 目录和包
- 与Java一样,在文件开头声明
package
,则该文件中定义的所有声明(类,函数,属性)都会属于这个包 - 导入包使用
import
关键字,可以使用*
在指定包下的所有类 - 在Kotlin中,可以吧多个类放在同一个文件中,但应该使用Java的包使用规则
package geometry.shapes
import java.util.Random //使用java的工具包
class Rectangle(val height: Int, val width: Int) {
val isSquare: Boolean
get() = height == width
}
fun createRandomRectangle(): Rectangle {
val random = Random()
return Rectangle(random.nextInt(), random.nextInt())
}
package geometry.example
import geometry.shapes.createRandomRectangle //使用上面的对象
fun main(args: Array) {
println(createRandomRectangle().isSquare)
}
6.选择语句when
-
1 . 枚举中使用
when
-
when
是一个有返回值的表达式,因此可以直接返回表达式函数体 -
分支语句上无需使用
break
enum class Color { RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET } fun getMnemonic(color: Color) = //直接返回when表达式 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
) { println(getMnemonic(Color.BLUE)) } /** * 合并多个选项 */ fun getWarmth(color: Color) = when(color) { Color.RED, Color.ORANGE, Color.YELLOW -> "warm" Color.GREEN -> "neutral" Color.BLUE, Color.INDIGO, Color.VIOLET -> "cold" } fun main(args: Array ) { println(getWarmth(Color.ORANGE)) } /** * 可导入枚举常量,从而简化代码 */ import ch02.colors.Color import ch02.colors.Color.* fun getWarmth(color: Color) = when(color) { RED, ORANGE, YELLOW -> "warm" GREEN -> "neutral" BLUE, INDIGO, VIOLET -> "cold" } fun main(args: Array ) { println(getWarmth(Color.ORANGE)) }
-
-
2 . 在
when
结构中使用任意对象-
与Java中的switch不一样,可以使用任意对象
import ch02.colors.Color import ch02.colors.Color.* fun mix(c1: Color, c2: Color) = when (setOf(c1, c2)) { //表达式匹配表达式 setOf(RED, YELLOW) -> ORANGE setOf(YELLOW, BLUE) -> GREEN setOf(BLUE, VIOLET) -> INDIGO else -> throw Exception("Dirty color") } fun main(args: Array
) { println(mix(BLUE, YELLOW)) }
-
-
3 . 不带参数的
when
-
如果没有给when表达式提供参数,则分支条件就是任意的布尔表达式(当做if来使用)
import ch02.colors.Color import ch02.colors.Color.* fun mixOptimized(c1: Color, c2: Color) = when { (c1 == RED && c2 == YELLOW) || (c1 == YELLOW && c2 == RED) -> ORANGE (c1 == YELLOW && c2 == BLUE) || (c1 == BLUE && c2 == YELLOW) -> GREEN (c1 == BLUE && c2 == VIOLET) || (c1 == VIOLET && c2 == BLUE) -> INDIGO else -> throw Exception("Dirty color") } fun main(args: Array
) { println(mixOptimized(BLUE, YELLOW)) }
-
-
4 . 使用when代替if
- 在kotlin中没有三元运算符,因为if表达式有返回值
-
在使用代码块时,代码块的最后一条表达式就是结果
interface Expr class Num(val value: Int) : Expr class Sum(val left: Expr, val right: Expr) : Expr /** * 使用if */ fun eval(e: Expr): Int = if (e is Num) { e.value } else if (e is Sum) { eval(e.right) + eval(e.left) } else { throw IllegalArgumentException("Unknown expression") } /** * 使用when替换if */ 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 evalWithLogging(e: Expr): Int = when (e) { is Num -> { println("num: ${e.value}") e.value } is Sum -> { val left = evalWithLogging(e.left) val right = evalWithLogging(e.right) println("sum: $left + $right") left + right } else -> throw IllegalArgumentException("Unknown expression") } fun main(args: Array
) { println(eval(Sum(Num(1), Num(2)))) }
-
5 . 迭代
while
和for
循环-
while
循环和Java一致 -
区间数字
* 一个起始值,一个结束值,使用`..`运算符来表示区间`val oneToTen = 1 .. 10` * Kotlin中的区间是包含的或者闭合的,即第二个值始终是区间的一部分 * 如果能迭代区间中所有的值,这样的区间被称为数列
-
downTo
表示降序 -
step
表示步长,在普通区间和降序区间中都能使用 -
until
表示开区间的结束/** * 区间[1,100] */ for(i in 1 .. 100 ){ println(i) } /** * 区间[1,100) */ for(i in 1 until 100 ){ println(i) } /** * 区间[100,1] 降序使用downTo */ for(i in 100 downTo 1 ){ println(i) } /** * 区间[100,1? 降序,并且指定步长 */ for(i in 100 downTo 1 step 2 ){ println(i) } /** * 区间[1,100? */ for(i in 1 .. 100 step 2 ){ println(i) }
-
-
-
迭代Map
fun main(args: Array
) { val binaryReps = TreeMap () for (c in 'A'..'F') { val binary = Integer.toBinaryString(c.toInt()) binaryReps[c] = binary } for ((letter, binary) in binaryReps) { println("$letter = $binary") } }
-
-
-
使用下标迭代List
val list = arrayListOf("10","11","12") for((index,element) in list.withIndex()){ println("$index:$element") }
-
-
-
in
/!in
运算符,可以检查一个值是否在区间内,或者不在区间内 - 在
when
语句中也可使用in
`运算符 -
in
运算符使用于所有实现java.lang.Comparable
接口的类fun isLetter(c: Char) = c in 'a'..'z' || c in 'A'..'Z' fun isNotDigit(c: Char) = c !in '0'..'9' fun main(args: Array
) { println(isLetter('q')) println(isNotDigit('x')) } fun recognize(c: Char) = when (c) { in '0'..'9' -> "It's a digit!" in 'a'..'z', in 'A'..'Z' -> "It's a letter!" else -> "I don't know…" } fun main(args: Array
) { println(recognize('8')) }
-
-
Kotlin中的异常
- 异常不需
new
关键字来创建实例 - Kotlin中的
throw
可以作为另一个表达式的一般部分 - Kotlin中,无需使用
throws
关键在来抛出异常,因为Kotlin中并不区分受检测异常和并不受检测异常,所以在代码中可以处理异常,也可不处理异常 - JDK1.7中的
try-with-resources
在kotlin中为一个库函数,在后面会介绍 -
try
关键字和if
、when
一样,可以作为表达式赋值给一个变量,但必须用花括号把语句主体包裹起来,如果主体包含多个表达式,则try
表达式的值就是最后一个表达式的值 -
catch
语句中也需要有返回值或者直接return
import java.io.BufferedReader import java.io.StringReader fun readNumber(reader: BufferedReader): Int? { //无需throws try { val line = reader.readLine() return Integer.parseInt(line) } catch (e: NumberFormatException) { //类型在右边 return null } finally { reader.close() } } fun main(args: Array
) { val reader = BufferedReader(StringReader("239")) println(readNumber(reader)) } -
无finally语句
import java.io.BufferedReader import java.io.StringReader fun readNumber(reader: BufferedReader) { val number = try { Integer.parseInt(reader.readLine()) } catch (e: NumberFormatException) { return //return 中断逻辑执行 //null //也可返回null } println(number) } fun main(args: Array
) { val reader = BufferedReader(StringReader("not a number")) readNumber(reader) }
- 异常不需