Kotlin从入门到精通 | 第三章 Kotlin内置类型

本章节主要介绍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; // ok but not good.
long d = 1234567890L; // ok

在Kotlin里面,直接就编译不通过,强制要求修改为L

val c = 1234567890l // compile error.
val d = 1234567890L // ok

Kotlin数值类型转换

在Java里,int类型可以隐式转换为long

int e = 10;
long f = e; // implicit conversion

而到了Kotlin这,对不起,不支持

val e: Int = 10
val f: Long = e // implicitness not allowed
val f: Long = e.toLong() // ok

无符号类型(兼容C Native)

从v1.3开始,Kotlin支持无符号类型
Kotlin从入门到精通 | 第三章 Kotlin内置类型_第1张图片

字符串定义

先看下Kotlin定义HTML字符串的代码

val n = """
    
    
    
        
        Hello World
    
    
        

Hello World

This is a demo page.

"""
.trimIndent() println(n)

对比Java,简直太简洁了,使用Java定义的一段同样行为的代码,一堆换行符,看了都头大
Kotlin从入门到精通 | 第三章 Kotlin内置类型_第2张图片

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 }

Kotlin从入门到精通 | 第三章 Kotlin内置类型_第3张图片

数组的长度

Java

int[] a = new int[5];
System.out.println(a.length); // only array uses 'length'

Kotlin

val a = IntArray(5)
println(a.size) // same with the Collections(e.g. List)

数组的读写

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 // [1,10]
val charRange = 'a'..'z'
val longRange = 1L..100L

开闭区间,前闭后开(until)

val intRangeExclusive = 1 until 10 // [1,10)
val charRangeExclusive = 'a' until 'z'
val longRangeExclusive = 1L until 100L

倒序区间(downTo)

val intRangeReverse = 10 downTo 1 // [10,9,...,1]
val charRangeReverse = 'z' downTo 'a'
val longRangeReverse = 100L downTo 1L

区间的步长(step)

在定义区间时,我们还可以定义步长,默认步长为1

val intRangeWithStep = 1..10 step 2 // [1, 3, 5, 7, 9]
val charRange = 'a'..'z' step 2
val longRange = 1L..100L step 5

区间的迭代

区间的迭代跟数组基本是类似的

for(element in intRange) {
  println(element)
}

intRange.forEach{ println(it) } // 高阶函数默认的参数叫做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 Map
可变Map MutableMap Map
不可变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) // 其中的 "name" to "benny" 是一个中缀表达式

集合实现类复用与类型别名

我们来比较一下Java与Kotlin创建集合的代码
Java

List<String> stringList = new ArrayList<>(); // java.util.ArrayList

Kotlin

val stringList = ArrayList<String>() // kotlin.collections.ArrayList

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

可以理解为键值对,包含firstsecond两个字段的数据结构

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里面,函数也是类型的一种,是一等公民,可以赋值、传递,并在合适的条件下调用

学习路线图

Kotlin从入门到精通 | 第三章 Kotlin内置类型_第4张图片

函数的定义

一个函数包含:函数名,函数参数列表,函数返回值,函数体

fun main(args: Array<String>):Unit {
  println(args.contentToString())
}

函数 VS 方法

  • 方法可以认为是函数的一种特殊类型
  • 从形式上,有receiver的函数即为方法

函数的类型

在Kotlin里,函数也是有类型的

fun foo() { } // () -> Unit
fun foo(p(): Int): String { ... } // (Int) -> String

class Foo {
  fun bar(p0: String, p1: Long): Any { ... } // Foo.(String, Long) -> Any,其中 Foo就是bar方法的receiver,类型等同于 (Foo, String, Long) -> Any
}

函数的引用

函数的引用类似于C语言中的函数指针,可用于函数传递

fun foo() { } // val f: () -> Unit = ::foo
fun foo(p(): Int): String { ... } // val g: (Int) -> String = ::foo

class Foo {
  fun bar(p0: String, p1: Long): Any { ... } // val h: (Foo, String, Long) -> Any = Foo::bar
}

绑定receiver的函数引用

val foo = Foo()
val m: (String, Long) -> Any = foo::bar // 绑定receiver的函数引用,其中foo是对象实例

f(r, x, y) = r * (x + y)
// 令:r = 2
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") // 这里的z使用默认的0L

具名函数

fun defaultParameter(x: Int = 5, y: String, z: Long = 0L) { // 不是最后的参数
  TODO()
}

defaultParameter(y = "Hello") // 只传递y参数,其余使用默认值

你可能感兴趣的:(kotlin,android,java)