ITKeyword,专注技术干货聚合推荐

注册 | 登录

Kotlin Primer 数据类型与程序结构

smartbetter 分享于 2017-06-23

推荐:数据结构(C语言版)第一章 抽象数据类型的表示与实现

//文件名:Triplet.c //因为C语言没有引用,所以用指针代替引用 //函数的头文件 #include <stdio.h> #include <stdlib.h> //函数结果状态码 #define TRUE 1 #def

2019阿里云双12.12最低价产品入口(新老用户均可),
地址https://www.aliyun.com/minisite/goods

转载请注明出处:http://blog.csdn.net/smartbetter/article/details/73441323

Kotlin是一门可以运行在Java虚拟机、Android、浏览器上的基于 jvm 的静态类型编程语言,100%兼容Java。Kotlin可以进行前端开发(js)、服务端开发(jvm)、甚至还可以编译成机器码直接跑在操作系统上(Native,本地执行程序)。

相比于 Java,Kotlin 有着更好的语法结构,安全性和开发工具支持。Kotlin 中没有基础类型,数组是定长的,泛型是安全的,即便运行时也是安全的。此外,该语言支持闭包,还可通过内联进行优化。不过,它不支持检查异常。不论如何,重要的是 Java 和 Kotlin 之间的互操作性:Kotlin 可以调用 Java,反之亦可。本篇将主要从 Kotlin 的数据类型出发,完整的学习下 Kotlin 的数据类型(官方文档中文文档)。

准备工作:我们选用 IDEA 用来开发 Kotlin 应用程序,使用 IDEA 创建 Kotlin 工程的步骤:IDEA -> New Project -> Gradle -> Kotlin。

1.数据类型

1.Boolean类型和Number类型

// Boolean类型
val FINAL_Boolean_A: Boolean = true // 运行时常量(可以通过反射修改)
const val FINAL_Boolean_B: Boolean = true // 编译期常量(完全不可修改,可以提高运行效率)
val e: X by lazy { // 延迟初始化(运行时)的常量
    X()
}
var aBoolean: Boolean = true // 变量
lateinit var aBoolean: Boolean // 延迟初始化(运行时)的变量

// Number类型,Number类型包括整型和浮点型。
val aInt: Int = 8
val anotherInt: Int = 0xFF
val moreInt: Int = 0b00000011
val maxInt: Int = Int.MAX_VALUE
val minInt: Int = Int.MIN_VALUE

val aLong: Long = 12368172397127391
val another: Long = 123
val maxLong: Long = Long.MAX_VALUE
val minLong: Long = Long.MIN_VALUE

val aFloat: Float = 2.0F
val anotherFloat: Float = 1E3f
val maxFloat: Float = Float.MAX_VALUE
val minFloat: Float = -Float.MAX_VALUE

val aDouble: Double = 3.0
val anotherDouble: Double = 3.1415926
val maxDouble: Double= Double.MAX_VALUE
val minDouble: Double= -Double.MAX_VALUE

val aShort: Short = 127
val maxShort: Short = Short.MAX_VALUE
val minShort: Short = Short.MIN_VALUE

val maxByte: Byte = Byte.MAX_VALUE
val minByte: Byte = Byte.MIN_VALUE

// jvm 的入口函数
fun main(args: Array<String>) {
    println(aInt)
}

2.Char类型和字符串

一个Char类型占2个字节,表示一个16位的Unicode字符。

// Char类型
val aChar: Char = '0'
val bChar: Char = 'a'
val cChar: Char = '中'
val dChar: Char = '\n'  // 换行符

// 字符串
val string: String = "Hello"
val fromChars: String = String(charArrayOf('H', 'e','l','l','o')) // 字符串类型也可以用字符进行构造
val rawString: String = """ \t \n """ // 原始字符串,输出结果不会变,转义字符也不会转义
fun main(args: Array<String>) {
    println(rawString.length) // 字符串长度
    val arg1: Int = 0
    val arg2: Int = 1
    println("$arg1 + $arg2 = ${arg1 + arg2}") // 支持字符串模版,$arg1就表示0,输出结果 0 + 1 = 1
}

其中Char类型的转义字符包含:

转义字符 含义 转义字符 含义 \t 制表符 \b 光标后退一个字符 \n 换行符 \r 光标回到行首 \’ 单引号 \” 双引号 \ \ 反斜杠 \ $ 美元符号

字符串比较用”==”比较内容,用”===”比较对象是否相同。

3.基础数据类型的转换

val aInt: Int = 5
val aLong: Long = aInt.toLong()     // 基础数据类型的转换不可隐式转换

4.面向对象的Kotlin程序

下面我们来看Kotlin面向对象的一些特性:

class Student constructor(name: String, age: Int): Person(name){
    fun printName() {
        println(name)
    }
}

open class Person(var name: String){
    init {
        println("new 了一个${this.javaClass.simpleName}, ta_name:$name")
    }
}

fun main(args: Array<String>) {
    val aStudent: Student = Student("zhangsan", 18)
    println(aStudent is Person)
    aStudent.printName()
}

输出结果:

new 了一个Student, ta_name:zhangsan
true
zhangsan

Kotlin 创建对象的时候并不需要new关键字,而是像调用普通方法一样直接调用构造方法就可以了。Kotlin中所有类最终都继承自Any。

5.空安全类型

fun getName(): String?{ // String? 代表可null字符串
    return null
}

fun main(args: Array<String>) {
    val value: String? = "HelloWorld"
    println(b?.length) // 安全操作符,如果b不为空,就返回长度,为空就返回null;
    val name: String = getName() ?: return // Elvis操作符,?:左边的返回值不为null则返回,否则返回右边的值
    println(value!!.length) // !!操作符,抛出一个非空的B或者空npe(nullPointException)
}

任意类型都有可空和不可空两种:

val notNull: String 不能为空,            val nullable: String? 可以为空
notNull.length 不为空的值可以直接使用,     nullable.length 可能为空,不能直接获取长度
nullable!!.length 强制认定nullable不可空, nullable?.length 若nullable为空,返回空

6.智能类型转换

fun main(args: Array<String>) {
    val parent: Parent = Parent()
    val child: Child? = parent as? Child // 安全类型转换
    println(child.name)

    val parent2: Parent = Child()
    if(parent2 is Child) {
        println(parent2.name) // 智能类型转换
    }
    val string: String? = "Hello"
    if(string != null)
        println(string.length)
}

类似 Java 的类型转换:

val sub: SubClass = parent as SubClass      // 类似Java的类型转换,失败则抛异常

安全类型转换:

val sub: SubClass? = parent as? SubClass        // 如果转换失败则返回null,不抛异常

智能类型转换:

if(parent is SubClass) parent.<子类的成员>   // 编译器尽可能的推导类型,远离无用的类型转换

if(nullable != null) nullable.length

7.区间

ClosedRange 的子类,IntRange 最常用。

val range: IntRange = 0..1024 // 表示 [0, 1024]
val range_exclusive: IntRange = 0 until 1024 // 表示 [0, 1024) = [0, 1023]

val emptyRange: IntRange = 0..-1

fun main(args: Array<String>) {
    println(emptyRange.isEmpty())
    println(50 in range) // 判断50是否在range区间中,也可以用 range.contains(50) 判断

    for(i in range_exclusive){ // 迭代输出range_exclusive
        print("$i, ")
    }
}

输出结果为:

true
true
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... 1022, 1023, 1024,

8.数组

基本写法:val array: Array< String> = arrayOf( … )
基本操作:print array[i] 输出第i个成员;array[i] = “Hello” 给第i个成员赋值;array.length 数组的长度。

为了避免不必要的装箱和拆箱,Kotlin 基本类型的数组都是定制的,下面看一下 Kotlin 与 Java 的对比:

推荐:在C语言中各种数据类型各占多少位 C语言 中结构体的位域(位段)

(一)32位平台: 分为有符号型与无符号型。 有符号型: short 在内存中占两个字节,范围为-2^15~(2^15-1) int 在内存中占四个字节,范围为-2^31~(2^31-1

Java Kotlin Java Kotlin int[] IntArray short[] ShortArray long[] LongArray float[] FloatArray double[] DoubleArray char[] CharArray
val arrayOfInt: IntArray = intArrayOf(1,2,3)    // 整型数组
val arrayOfChar: CharArray = charArrayOf('H', 'e','l','l','o')  // 字符数组
val arrayOfString: Array<String> = arrayOf("He", "ll", "o") // 字符串数组
val arrayOf类: Array<类> = arrayOf(类("A"), 类("B"), 类("C"))     // 对象数组

fun main(args: Array<String>) {
    arrayOfInt.forEach { // 遍历数组 方式一
        print(it)
    }
    arrayOfInt.forEach(::print)  // 方式一简写
    arrayOfInt.forEach ForEach@{  // 加了一个ForEach标签
        if (it == 2) return@ForEach // 终止遍历,如果不加标签,会直接终止了 main 函数
        print(it)
    }
    for(int in arrayOfInt){ // 遍历数组 方式二
        print(int)
    }

    print(arrayOf类[1])
    arrayOf类[1] = 类("D") // 修改元素的值
    println(arrayOf类[1])

    println(arrayOfChar.joinToString("")) // 拼接成字符串,传空参数是为了去除逗号
    println(arrayOfInt.slice(1..2)) // 字符串切片,取[1, 2]之间对应的元素
}

输出结果为:

1231231123BD
Hello
[2, 3]

另外,在 Kotlin 中,跳出当前循环用 continue,终止循环用 break,多层循环嵌套的终止需要结合标签使用。

2.程序结构

1.函数与Lambda表达式

Kotlin 中定义函数(function)是用 fun 修饰的,如上我们已经用到了 main 函数,需要注意的是,像 main 函数这种什么都不返回的函数,实际上是返回了 Unit:

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

下面我们定义几个带返回值的函数:

// 方式一,具名函数
fun sum(arg1: Int, arg2: Int): Int {
    return arg1 + arg2
}
// 方式二,具名函数,像这种函数体是一个表达式的情况,可以简写
fun sum(arg1: Int, arg2: Int) = arg1 + arg2

// 匿名函数
val int2Long = fun(arg1: Int, arg2: Int): Int {
    return arg1 + arg2
}

// Lambda表达式定义sum函数,Lambda表达式其实就是匿名函数
val sum = { arg1: Int, arg2: Int -> arg1 + arg2 }
// Lambda表达式的返回值实际上是最后一行的值,(Int, Int) -> Int
val sum = { arg1: Int, arg2: Int -> 
    println("hello")
    arg1 + arg2 }

在 Lambda 表达式中 () -> Unit 表示无参,返回值为 Unit,(Int) -> Int 表示传入整型,返回一个整型值,(String, (String) -> String) -> Boolean 表示传入字符串、Lambda 表达式,返回 Boolean。

Lambda 表达式用 () 进行调用,等价于 invoke() 方法,例如:

val sum = { arg1: Int, arg2: Int -> arg1 + arg2 }
sum(1, 2) // 等价于 sum.invoke(1, 2)

Lambda 表达式的简化:
1. 函数参数调用时最后一个 Lambda 可以移出去;
2. 函数参数只有一个 Lambda,调用时小括号可省略;
3. Lambda 只有一个参数可默认为 it;
4. 入参、返回值与形参一致的函数可以用函数引用的方式作为实参传入。

补充:基本运算符相关中文文档:https://www.kotlincn.net/docs/reference/operator-overloading.html

2.类成员与参数

1.类成员

class Person(name: String, age: Int){
    var a = 0
    lateinit var b: String // 延迟初始化
    val c: X by lazy { // 延迟初始化
        X()
    }

    // 成员方法
    fun say(arg: String) {
        // 具体实现
    }
}
fun main(args: Array<String>) {
    val aPerson = Person("zhangsan", 18)
    aPerson.say("Hello")
}

属性初始化尽量在构造方法中完成,如果无法在构造方法中初始化,那么尝试降级为局部变量。var 用 lateinit 延迟初始化,val 用 lazy,可空类型谨慎用 null 直接初始化。

2.参数

  1. 具名参数,给函数的实参附上形参:
fun sum(arg1: Int, arg2: Int) = arg1 + arg2
sun(arg2 = 2, arg1 = 1) // arg1 与 arg2 顺序交换也没有关系
  1. 变长参数:
fun hello(double: Double, vararg ints: Int, string: String){
    println(double)
    ints.forEach(::print)
    println(string)
}
fun main(args: Array<String>) {
    hello(3.0, 1, 2, 3, string = "hello") // 如果传参时有歧义,需要使用具名参数

    val array = intArrayOf(1, 2, 3)
    hello(3.0, *array, string = "hello") // *表示将array展开
}

输出结果为:

3.0
123hello
3.0
123hello
  1. 默认参数:
fun sum(arg1: Int = 1, arg2: Int) = arg1 + arg2 // 设置 arg1 默认为1

3.表达式与循环语句

1.中缀表达式

只有一个参数,且用 infix 修饰的函数。可以去掉点和小括号来调用这个函数,例如:

class Person{ infix fun printName(name: String){...}}

fun main(args: Array<String>) {
    Book() on "zhangsan"
}

2.分支表达式

if 表达式:

private const val A = 1;
private const val B = 0;

fun demo(arg1: String) {
    val mode = if(arg1.isNotEmpty()){
        A
    } else {
        B
    }
}

when 表达式(加强版的 switch,支持任意类型,支持纯表达式的条件分支):

enum class State {
    A, B, C, D
}
var state = State.A

when (state) {
    A, B -> doSomeThing()
    else -> {
    }
}

4.异常捕获

try{ }catch(e: Exception){ }finally{ }

其实和if/when表达式类似,try…catch 也是表达式,可以用来赋值:

val result = try{ 1 }catch(e: Exception){ 0 }finally{ }

还有一种写法如下,会先执行 finally 中的代码,然后再返回:

return try{ 1 }catch(e: Exception){ 0 }finally{ }

3.编码风格

Kotlin 编码风格与 Java 类似(驼峰命名法),类名首字母大写,每个单词的首字母大写;方法和属性变量首字母小写;采用四个空格缩进。另外官方文档中建议在 Kotlin 语言中不要给属性前面加前缀,例如通常我们习惯加上一个小写m或者下划线等。

冒号,在分隔两个类型的时候,应该在左右都有空格;在实例和类型之间,应该紧靠实例变量,例如:

interface Foo<out T : Any> : Bar {
    fun foo(a: Int): T
}

Lambda表达式,如果是简单的只用一行就可以表示的 lambda,应当遵循在大括号的两侧、箭头的两侧、参数的两侧都使用空格隔开,例如:

list.filter { it > 10 }.map { element -> element * 2 }

推荐:C语言程序设计进阶-Chap01-数据类型

云课堂课程,由浙江大学翁恺老师讲授。 1.0 数据类型 C是有类型的语言 C语言的变量,必须 在使用前定义,并且 确定类型 C以后的语言向两个方向发展 C++/Java 更

转载请注明出处:http://blog.csdn.net/smartbetter/article/details/73441323 Kotlin是一门可以运行在Java虚拟机、Android、浏览器上的基于 jvm 的静态类型编程语言,100%兼容Java。Kotlin可以

相关阅读排行


用户评论

游客

相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。