本章节主要介绍Kotlin的内置类型和简单用法
变量的声明
val b: String = "Hello Kotlin"
Kotlin的变量声明方式,有点类似于TypeScript ,是比较现代的一种做法,一般形式为修饰符 变量名: 类型 = 值 ,其中,类型声明可以省略。
修饰符有两种
- val:只读变量
- var:可读写变量,定义时必须指定值,且不可更改
与Java对比
int a = 2;
final String b = "Hello Java";
var a = 2
val b = "Hello Kotlin"
易混淆的Long类型标记
在Java里,Long 类型结束使用l 是可以编译通过,只是不推荐(小写的l ,看起来就跟数字1一样)
long c = 1234567890l;
long d = 1234567890L;
在Kotlin里面,直接就编译不通过,强制要求修改为L
val c = 1234567890l
val d = 1234567890L
Kotlin数值类型转换
在Java里,int 类型可以隐式转换为long
int e = 10;
long f = e;
而到了Kotlin这,对不起,不支持
val e: Int = 10
val f: Long = e
val f: Long = e.toLong()
无符号类型(兼容C Native)
从v1.3开始,Kotlin支持无符号类型
字符串定义
先看下Kotlin定义HTML字符串的代码
val n = """
<!doctype html>
<html>
<head>
<meta charset="UTF-8"/>
<title>Hello World</title>
</head>
<body>
<div id="container">
<H1>Hello World</H1>
<p>This is a demo page.</p>
</div>
</body>
</html>
""".trimIndent()
println(n)
对比Java,简直太简洁了,使用Java定义的一段同样行为的代码,一堆换行符,看了都头大
Kotlin字符串
字符串比较
a == b :比较内容,等价于Java的equals a === b :比较对象是否是同一个对象
字符串模板
- “hello, $name” => “Hello, 小明”
数组
| Kotlin | Java |
---|
整型 | IntArray | int[] | 整型装箱 | Array | Integer[] | 字符 | CharArray | char[] | 字符装箱 | Array | Character[] | 字符串 | Array | String[] |
数组的创建
int[] c = new int[]{1, 2, 3, 4, 5};
在Kotlin里面,数组使用以下方式创建
val c0 = intArrayOf(1, 2, 3, 4, 5)
val c1 = IntArray(5){ it + 1 }
数组的长度
Java
int[] a = new int[5];
System.out.println(a.length);
Kotlin
val a = IntArray(5)
println(a.size)
数组的读写
Java
String[] d = new String[]{"Hello", "World"};
d[1] = "Java";
System.out.println(d[0] + ", " + d[1]);
Kotlin
val d = arrayOf("Hello", "World")
d[1] = "Kotlin"
println("${d[0]}, ${d[1]}")
数组的遍历
Java
float[] e = new float[]{1, 3, 5, 7};
for(float element : e) {
System.out.println(element);
}
Kotlin,有点像Python里面的元素遍历了
val e = floatArrayOf(1f, 3f, 5f, 7f)
for (element in e) {
println(element)
}
或者还可以使用forEach 高阶函数
e.forEach { element -> println(element) }
数组的包含关系
Java
for(float element : e) {
if(element == 1f) {
System.out.println("1f exists in variable 'e'");
break;
}
}
而在Kotlin里面,简单的不行
if(1f in e) {
println("1f exists in variable 'e'")
}
区间
这个Java里是没有,所以只看Kotlin的写法
区间的创建
闭区间(…)
val intRange = 1..10
val charRange = 'a'..'z'
val longRange = 1L..100L
开闭区间,前闭后开(until)
val intRangeExclusive = 1 until 10
val charRangeExclusive = 'a' until 'z'
val longRangeExclusive = 1L until 100L
倒序区间(downTo)
val intRangeReverse = 10 downTo 1
val charRangeReverse = 'z' downTo 'a'
val longRangeReverse = 100L downTo 1L
区间的步长(step)
在定义区间时,我们还可以定义步长,默认步长为1
val intRangeWithStep = 1..10 step 2
val charRange = 'a'..'z' step 2
val longRange = 1L..100L step 5
区间的迭代
区间的迭代跟数组基本是类似的
for(element in intRange) {
println(element)
}
intRange.forEach{ println(it) }
区间的包含关系
if(3 in intRange) {
println("3 in range 'intRange'")
}
if(12 !in intRange) {
println("12 not in range 'intRange'")
}
区间的应用
val array = intArrayOf(1, 3, 5, 7)
for(i in array.indices) {
println(array[i])
}
其中,array.indices 返回的就是数组索引范围的区间
集合框架
Kotlin在Java集合的基础上,做出了一些增强,具体表现为以下几点
- 增加了“不可变”集合框架的接口
- 没有另起炉灶,复用Java Api的所有实现类型
- 提供了丰富医用的方法,例如
forEach/map/flatMap 等
Scala也是一门JVM语言,Kotlin很多特性都参考了Scala
集合框架的接口类型对比
| Kotlin | Java |
---|
不可变List | List | List | 可变List | MutableList | List | 不可变Map | Map<K, V> | Map<K, V> | 可变Map | MutableMap<K, V> | Map<K, V> | 不可变Set | Set | Set | 可变Set | MutableSet | Set |
集合框架的创建
Java
List<Integer> intList = new ArrayList<>(Arrays.asList(1, 2, 3));
Kotlin
val intList: List<Int> = listOf(1, 2, 3)
val intList2: MutableList<Int> = mutableListOf(1, 2, 3)
val map: Map<String, Any> = mapOf("name" to "benny", "age" to 20)
val map2: Map<String, Any> = mutableMapOf("name" to "benny", "age" to 20)
集合实现类复用与类型别名
我们来比较一下Java与Kotlin创建集合的代码 Java
List<String> stringList = new ArrayList<>();
Kotlin
val stringList = ArrayList<String>()
Kotlin里面集合的类型别名定义
@SinceKotlin("1.1") public actual typealias ArrayList<E> = java.util.ArrayList<E>
@SinceKotlin("1.1") public actual typealias LinkedHashMap<K, V> = java.util.LinkedHashMap<K, V>
@SinceKotlin("1.1") public actual typealias HashMap<K, V> = java.util.HashMap<K, V>
@SinceKotlin("1.1") public actual typealias LinkedHashSet<E> = java.util.LinkedHashSet<E>
@SinceKotlin("1.1") public actual typealias HashSet<E> = java.util.HashSet<E>
Kotlin使用类型别名,是出于跨平台的考虑,同一份代码,Kotlin不只是希望能跑在JVM平台,也可以是Native平台,所以,说不定有朝一日,Kotlin编译出来的不再是Java字节码,而是二进制机器码!
集合框架的读写
Kotlin还支持运算符重载
添加元素
Java
for(int i = 0; i < 10; i++) {
stringList.add("num: " + i);
}
Kotlin
for(i in 0..10) {
stringList += "num: $i"
}
删除元素
Java
for(int i = 0; i < 10; i++) {
stringList.remove("num: " + i);
}
Kotlin
for(i in 0..10) {
stringList -= "num: $i"
}
修改元素
Java
stringList.set(5, "HelloWorld");
String valueAt5 = stringList.get(5);
Kotlin
stringList[5] = "HelloWorld"
val valueAt5 = stringList[5]
如果是Map Java
HashMap<String, Integer> map = new HashMap<>();
map.put("Hello", 10);
System.out.println(map.get("Hello"));
Kotlin
val map = HashMap<String, Int>()
map["Hello"] = 10
println(map["Hello"])
几个重要的数据结构
Pair
可以理解为键值对,包含first 和second 两个字段的数据结构
val pair = "Hello" to "Kotlin"
val pair2 = Pair("Hello", "Kotlin")
val first = pair.first
val second = pair.second
val (x, y) = pair
Triple
跟Pair 类似,不过含有三个值
val triple = Triple("x", 2, 3.0)
val first = triple.first
val second = triple.second
val third = triple.third
val (x, y, z) = triple
函数
在Kotlin里面,函数也是类型的一种,是一等公民,可以赋值、传递,并在合适的条件下调用
学习路线图
函数的定义
一个函数包含:函数名,函数参数列表,函数返回值,函数体
fun main(args: Array<String>):Unit {
println(args.contentToString())
}
函数 VS 方法
- 方法可以认为是函数的一种特殊类型
- 从形式上,有
receiver 的函数即为方法
函数的类型
在Kotlin里,函数也是有类型的
fun foo() { }
fun foo(p(): Int): String { ... }
class Foo {
fun bar(p0: String, p1: Long): Any { ... }
}
函数的引用
函数的引用类似于C语言中的函数指针,可用于函数传递
fun foo() { }
fun foo(p(): Int): String { ... }
class Foo {
fun bar(p0: String, p1: Long): Any { ... }
}
绑定receiver的函数引用
val foo = Foo()
val m: (String, Long) -> Any = foo::bar
f(r, x, y) = r * (x + y)
m(x, y) = f(2, x, y) = 2 * (x + y)
变长参数(vararg关键字)
fun main(vararg args: String) {
println(args.contentToString())
}
多返回值
Pair或Triple定义返回值,使用结构获取返回值
fun multiReturnValues(): Triple<Int, Long, Double> {
return Triple(1, 3L, 4.0)
}
val (a, b, c) = multiReturnValues()
默认参数
Kotlin允许为参数指定默认值,这样一来,就不必像Java一样定义方法重载了
fun defaultParameter(x: Int, y: String, z: Long = 0L) {
TODO()
}
defaultParameter(5, "Hello")
具名函数
fun defaultParameter(x: Int = 5, y: String, z: Long = 0L) {
TODO()
}
defaultParameter(y = "Hello")
|