Kotlin 学习笔记(一) 基本类型和基本语法
来源:互联网 发布:网络没问题app网络异常 编辑:程序博客网 时间:2024/05/17 22:07
Kotlin 被提升为 Android 开发一级语言, 虽然短时间内 Java 并不会被取代, 不过学习 Kotlin 还是宜早不宜迟, 做好迎接变化的准备。
Android Studio 3.0 开始官方支持了 Kotlin, 因此, 先下一个 3.0 Preview 版 吧。
当前最新的 Preview 版是 Canary4。
学习资料
官方网站
中文站
《Kotlin for android developers》中文版翻译
Android 相关的官方示例
在线试用 Kotlin
基本类型
Char 不再是数字
数字类型之间不能通过赋值进行隐式提升, 比如把 Int 赋值给 Long, 但可以通过运算推断, 比如
Long b = 3L + 1 // Long + Int => Long
, 或者显式提升。不支持八进制, Long 类型需要标记 L, 如
Long a = 12L
浮点值默认推断为 Double, Float 表示为 1f 或者 1F
数字字面值可添加下划线方便阅读
val oneMillion = 1_000_000
虽然在 Kotlin 中类型都是对象, 但数字是作为 jvm 原生类型储存, 除非在可空类型(如
Int?
)或泛型时使用, 他们会被装箱。 装箱后和 java 中的装箱类相似,值相等(==)
但是对象不一定相同(===)
位运算符
这是完整的位运算列表(只用于 Int 和 Long):
shl(bits) – 有符号左移 (Java 的 <<)
shr(bits) – 有符号右移 (Java 的 >>)
ushr(bits) – 无符号右移 (Java 的 >>>)
and(bits) – 位与
or(bits) – 位或
xor(bits) – 位异或
inv() – 位非
val x = (1 shl 2) and 0x000FF000
布尔
内置的布尔运算有:
|| – 短路逻辑或
&& – 短路逻辑与
! - 逻辑非
没有 &
和 |
fun arrays(){ /* 我们可以使用库函数 arrayOf() 来创建一个数组并传递元素值给它,这样 arrayOf(1, 2, 3) 创建了 array [1, 2, 3]。 或者,库函数 arrayOfNulls() 可以用于创建一个指定大小、元素都为空的数组。*/ val arrayOf = arrayOf(1, 2, 3) val arrayOfNulls = arrayOfNulls<Int>(5) /* 该构造第一个参数是 size, 第二个参数是一个 lamb 函数, 入参 i 代表数组 index * 返回给定 index 的每个元素初始值 */ val arr = Array(3,{i -> i }) for (i in arr) { println(i) }}
字符串
字符串用 String 类型表示。字符串是不可变的。 字符串的元素——字符可以使用索引运算符访问: s[i]。 可以用 for 循环迭代字符串:
for (c in str) {
println(c)
}
字符串字面值
Kotlin 有两种类型的字符串字面值: 转义字符串可以有转义字符,以及原生字符串可以包含换行和任意文本。转义字符串很像 Java 字符串:
val s = "Hello, world!\n"
转义采用传统的反斜杠方式。参见上面的 字符 查看支持的转义序列。
原生字符串 使用三个引号(”“”)分界符括起来,内部没有转义并且可以包含换行和任何其他字符:
val text = """ for (c in "foo") print(c)"""
你可以通过 trimMargin() 函数去除前导空格:
val text = """ |Tell me and I forget. |Teach me and I remember. |Involve me and I learn. |(Benjamin Franklin) """.trimMargin()
默认 | 用作边界前缀,但你可以选择其他字符并作为参数传入,比如 trimMargin(“>”)。
字符串模板
字符串可以包含模板表达式 ,即一些小段代码,会求值并把结果合并到字符串中。 模板表达式以美元符($)开头,由一个简单的名字构成:
val i = 10val s = "i = $i" // 求值结果为 "i = 10"
或者用花括号扩起来的任意表达式:
val s = "abc"val str = "$s.length is ${s.length}" // 求值结果为 "abc.length is 3"
原生字符串和转义字符串内部都支持模板。 如果你需要在原生字符串中表示字面值 $ 字符(它不支持反斜杠转义),你可以用下列语法:
val price = """${'$'}9.99"""
基础语法
结尾不需要加分号
方法通过
fun
关键字声明函数可以作为参数传递, 支持 lambda
定义局部变量
变量有 2 种,
var
代表可变变量,val
代表不可变变量, 赋值后不可再次赋值如果是直接赋值的写法, 变量的类型可通过值自动推断, 可以声明也可以省略
如果没有初始赋值, 类型必须声明
val a: Int = 1 // 立即赋值val b = 2 // 自动推断出 `Int` 类型val c: Int // 如果没有初始值类型不能省略c = 3 // 明确赋值
定义函数
/** * 两个 Int 相加 返回 Int */fun sum(a: Int, b: Int): Int { return a + b}/** * 自动推断参数类型和返回结果的写法 */fun sum1(a: Int, b: Int) = a + b/** * * 标准写法, 无返回值类型时, 返回值类型声明 : Unit 可以省略 * * fun printSum(a: Int, b: Int): Unit { * println("sum of $a and $b is ${a + b}") * } */fun printSum(a: Int, b: Int) { // 字符串中可以通过'$'符号引用变量, ${} 作为函数 println("sum of $a and $b is ${a + b}")}
可空变量声明
当一个变量或者返回值可能为空, 需要在声明类型后面加上 ?
做可空声明,如 var a: Int?
。在明确赋值或者进行非空判断之前, 变量 a
的类型为 Int?
而非 Int
。
可空类型不可以直接使用, 需要转换为非空类型, 而这一步是编译器通过代码自动判断的。
fun parseInt(str: String): Int? { return str.toIntOrNull()}fun printProduct(arg1: String, arg2: String) { val x = parseInt(arg1) val y = parseInt(arg2) // 直接使用 `x * y` 可能会报错,因为他们可能为 null if (x != null && y != null) { // 在空检测后,x 和 y 会自动转换为非空值(non-nullable) println(x * y) } else { println("either'$arg1'or'$arg2'is not a number") } }
类型检测和自动类型转换
is
运算符检测一个表达式是否某类型的一个实例。 如果一个不可变的局部变量或属性已经判断出为某类型,那么检测后的分支中可以直接当作该类型使用,无需显式转换:
fun getStringLength(obj: Any): Int? { if (obj is String) { // `obj` 在该条件分支内自动转换成 `String` return obj.length } // 在离开类型检测分支后,`obj` 仍然是 `Any` 类型 return null}fun getStringLength(obj: Any): Int? { if (obj !is String) return null // `obj` 在这一分支自动转换为 `String` return obj.length}fun getStringLength(obj: Any): Int? { // `obj` 在 `&&` 右边自动转换成 `String` 类型 if (obj is String && obj.length> 0) { return obj.length } return null}
控制流
- 三元运算符被取消了, 因为
if
表达式可以直接返回值, 代替三元运算符的作用
/** * 使用条件表达式的推断返回值类型写法 */fun maxOf(a: Int, b: Int) = if (a > b) a else b
when
关键字代替并扩展了switch
关键字, 它也可以直接返回值或者与 函数、in
、is 等其他关键字配合, 扩展判断功能。
IF
if 的分支可以是代码块,最后的表达式作为该块的值:
val max = if (a> b) { print("Choose a") a} else { print("Choose b") b}
when
每个 ->
代表一个分支, 如果很多分支需要用相同的方式处理,则可以把多个分支条件放在一起,用逗号分隔:
when (x) { 0, 1 -> print("x == 0 or x == 1") else -> print("otherwise")}
如果其他分支都不满足条件将会求值 else 分支 (类似原来的 default)。 如果 when 作为一个表达式使用,则必须有 else 分支, 除非编译器能够检测出所有的可能情况都已经覆盖了。
fun hasPrefix(x: Any) = when(x) { is String -> x.startsWith("prefix") else -> false}
分支的判断条件种类
常量
任意表达式
when (x) { parseInt(s) -> print("s encodes x") else -> print("s does not encode x")}
in
在某个区间中, 或者!in
不在某个区间中, 区间是 java 没有的概念, 参考资料
区间示例:
for (i in 1..100) { …… } // 闭区间:包含 100for (i in 1 until 100) { …… } // 半开区间:不包含 100for (x in 2..10 step 2) { …… }// 每到第二步, 取值, 然后重新计步, 246810for (x in 10 downTo 1) { …… } // 从 10 到 1 倒序循环if (x in 1..10) { …… } // 判断是否处于区间内
when (x) { in 1..10 -> print("x is in the range") in validNumbers -> print("x is valid") !in 10..20 -> print("x is outside the range") else -> print("none of the above")}
is
是某个类型, 或者!is
不是某个类型
fun hasPrefix(x: Any) = when(x) { is String -> x.startsWith("prefix") else -> false}
代替 if, else if
如果不提供参数,所有的分支条件都是简单的布尔表达式,而当一个分支的条件为真时则执行该分支:
when { x.isOdd() -> print("x is odd") x.isEven() -> print("x is even") else -> print("x is funny")}
for
类似 Java 的增强 For, 使用迭代器, 对于数组的 for 会自动编译为使用索引的循环
for (item in collection) print(item)
如果你想要通过索引遍历一个数组或者一个 list, 使用如下格式
for (i in array.indices) { print(array[i])}
或者可以用库函数 withIndex
for ((index, value) in array.withIndex()) { println("the element at $index is $value")}
while
while
和 do..while
照常使用
fun useWhile() { // while 正常使用 var x = 3 while (x-- > 0) { print(x) } fun retrieveData() = x++ do { val y = retrieveData() print(y) } while (y < 3) // y 在此处可见}
- Kotlin 学习笔记(一) 基本类型和基本语法
- Kotlin学习笔记一(基本语法)
- Kotlin学习笔记一基本类型
- Kotlin 基本语法 (一)
- Kotlin基本语法一
- kotlin 基本语法(一)
- Kotlin学习(一)基本语法
- Kotlin学习(一):基本语法
- kotlin学习--基本语法
- Kotlin 学习笔记(1)基本语法
- kotlin基本语法与类型
- kotlin学习(一)kotlin的基本句法语法
- Kotlin学习笔记——基本类型
- Kotlin基本语法(一)
- Kotlin使用(一)基本语法
- Kotlin基本语法(一)
- Kotlin学习笔记(一) 基本数据类型
- Python学习笔记一 基本语法、变量类型、时间处理
- JSP开发报错:Can not find the tag library descriptor for "http://java.sun.com/jsp/jstl/
- ubuntu 无法获得锁 /var/lib/dpkg/lock
- 当前路径是否存在
- Spring mvc 绑定list参数
- 运行一个最简单的 electron 项目
- Kotlin 学习笔记(一) 基本类型和基本语法
- 内部功能
- Myeclipse连接mysql数据库并测试使用-简例
- Android复习知识点总结(一)
- C语言中【基本文件操作】
- Mysql Binlog三种格式介绍及分析
- i++与++i的区别
- HTML+CSS实现动态背景登录页面
- java的单例详解