当前位置: 首页 > article >正文

Kotlin 函数和变量(四)

导读大纲

    • 1.1 基本要素: 函数和变量
      • 1.1.1 声明变量以存储数据
      • 1.1.2 将变量标记为只读或可重新赋值
      • 1.1.3 更简单的字符串格式化: 字符串模板

1.1 基本要素: 函数和变量

  1. 本节将向你介绍每个 Kotlin 程序都包含的基本元素: 函数和变量

    • 你将编写自己的第一个 Kotlin 程序,了解 Kotlin 如何让你省略许多类型声明
      1. 以及它如何鼓励你尽可能避免使用可变数据–为什么这是件好事
  2. 承上–函数传送门

1.1.1 声明变量以存储数据

  1. 在所有 Kotlin 程序中,另一个常用的基本构件是变量,它允许你存储数据

    • Kotlin 中的变量声明以一个关键字(val 或 var)开头
      1. 然后是变量的名称
    • 虽然 Kotlin 可以让你省略许多变量声明的类型
      1. 得益于其强大的类型推断功能
    • 但你总是可以在变量名后显式地加上类型
  2. 例如,如果您需要在一个 Kotlin 变量中存储一个最著名的问题及其相应的答案

    • <1> 可以通过指定两个变量 question 和 answer 来实现
      1. 在变量名后显式地写上它们的类型
    • <2> 也可以省略类型声明,使示例更加简洁
      1. 与表达式体函数一样,如果不指定类型
        • 编译器会分析初始化表达式,并将其类型作为变量类型
      2. 这里初始化表达式 42 的类型是 Int,因此变量 answer 的类型也是 Int
    • <3> 如果使用浮点常量,变量的类型就是 Double
// <1>
val question: String = "The Ultimate Question of Life, the Universe, and Everything"
val answer: Int = 42
// =========================== <2>
val question = "The Ultimate Question of Life, the Universe, and Everything"
val answer = 42
val yearsToCompute = 7.5e6
  1. 如果您没有立即初始化变量
    • 而是在稍后才赋值,编译器将无法推断出变量的类型
      1. 在这种情况下,您需要明确指定变量的类型
      2. 否则会报错: Return type for property answer cannot be resolved
        在这里插入图片描述
fun main() {
    val answer: Int
    answer = 42              
}

1.1.2 将变量标记为只读或可重新赋值

  1. 为了控制变量何时可以分配新值,Kotlin提供两个关键字val和var来声明变量

    • val(from value)声明一个只读引用
      1. 用 val 声明的变量只能赋值一次,初始化后,就不能再赋值
        • 相比之下,在 Java 中,这可以通过 final 修饰符来表示
    • var(from variable)声明一个可重新赋值的引用
      1. 您可以将即使在初始化之后,也可以向此类变量添加其他值
        • 这种行为类似于 Java 中的non-final变量
  2. 默认情况下,在 Kotlin 中应尽量使用 val 关键字声明所有变量

    • 只有在必要时才将其改为 var
    • 使用只读引用、不可变对象和无副作用的函数
      1. 可以让你充分利用函数式编程风格带来的好处
  3. 执行定义 val 变量的代码块时,必须对该变量进行一次精确的初始化

    • 不过,只要编译器能确保只执行其中一条初始化语句
      1. 你也可以根据某些条件用不同的值来初始化它
    • 您可能会遇到这样的情况:您要为一个结果变量赋值
      1. 而这个结果变量的内容取决于另一个函数的返回值
    • <1> 编译器很聪明,知道两个可能的赋值中会有一个被执行
      1. 因此您仍然可以使用 val 关键字将 result 指定为只读引用
fun canPerformOperation(): Boolean {
    return true
}
fun main() {
    val result: String                     // <1>
    if (canPerformOperation()) {
        result = "Success"                 // <1>
    } else {
        result = "Can't perform operation" // <1>
    }
}
  1. 需要注意的是,尽管val引用本身是只读的,一旦赋值就不能更改
    • 它指向的对象可能是可变的
    • <1> 将一个元素添加到一个可变的列表
      1. 而该列表是由一个只读引用定义的,这完全没有问题
fun main() {
    val languages = mutableListOf("Java") 
    languages.add("Kotlin") 
}
  1. 尽管 var 关键字允许变量改变其值,但其类型是固定
    • 例如,如果你在程序进行到一半时决定答案变量应该存储字符串而不是整数
      1. 那么你就会遇到编译错误
        title
    • 编译器仅通过初始化器推断变量类型,在确定类型时不会考虑后续赋值
    • 如果需要在变量中存储类型不匹配的值
      1. 必须手动将该值转换强制转换为正确的类型

1.1.3 更简单的字符串格式化: 字符串模板

  1. 使用字符串模板来拼接字符串
    • 在代码中, 您通过 readln() 函数(可在任何 Kotlin 文件中使用)
      1. 从标准输入流中读取输入
    • 然后使用 if 表达式声明一个变量名初始化其值
      1. 如果标准输入流存在且不为空,那么 name 就会被赋值为 input
        • 否则, 它的默认值为"Kotlin"
      2. 最后, 在传递给 println 的字符串字面量中使用它
fun main() {
    val input = readln()
    val name = if (input.isNotBlank()) input else "Kotlin"
    println("Hello, $name!")
}
  1. 与许多脚本语言一样,Kotlin 允许在变量名前加上 $ 字符

    • 从而在字符串字面量中引用局部变量, 更紧凑,效率也一样高
      1. 这等同于 Java 的字符串连接(“Hello, " + name +”!")
    • 当然,表达式是经过静态检查的,如果您试图引用一个不存在的变量
      1. 代码将无法编译
    • 注意,对于 JVM 1.8 目标,编译后的代码会创建一个 StringBuilder
      1. 将常量部分和变量值附加到其中
    • 针对 JVM 9 或更高版本的应用程序
      1. 通过 invokedynamic 将字符串连接编译成更高效的动态调用
  2. 如果需要在字符串中包含 $ 字符,可以用反斜杠将其转义

    • <1> 不将 x 解释为变量引用
fun main() {
    println("\$x")            // <1>
}
  1. Kotlin 中的字符串模板非常强大,因为它们不会限制只能引用单个变量
    • 你也可以在字符串模板提供一个更复杂的表达式
      1. 只需在表达式周围加上大括号即可
    • <1> 使用 ${} 语法在问候语字符串中插入 name.length 属性
fun main() {
    val name = readln()
    if (name.isNotBlank()) {
        println("Hello, ${name.length}-letter person!")  // <1>
    }
    // Blank input: (no output)
    // "Seb" input: Hello, 3-letter person!
}
  1. 现在,你可以在字符串模板中包含任意表达式
    • 而且你已经知道 if 在 Kotlin 中也是一种表达式
      1. 将两者结合起来, 将条件直接包含在字符串模板
    • <1> 在字符串模板中,您仍然可以使用本身包含双引号字符串的表达式
      1. 当表达式被求值时,它会返回字符串"someone"或提供的名称
        • 将其插入到包围的模板
fun main() {
    val name = readln()
    println("Hello, ${if (name.isBlank()) "someone" else name}!")  // <1>
    // Blank input: Hello, someone!
    // "Seb" input: Hello, Seb!
}

http://www.kler.cn/a/315675.html

相关文章:

  • C++中string的新特性
  • PNG图片批量压缩exe工具+功能纯净+不改变原始尺寸
  • 专题十八_动态规划_斐波那契数列模型_路径问题_算法专题详细总结
  • HTTP常见的请求头有哪些?都有什么作用?在 Web 应用中使用这些请求头?
  • Leecode热题100-35.搜索插入位置
  • 前端常用布局模板39套,纯CSS实现布局
  • 双向链表:实现、操作与分析【算法 17】
  • 【Fastapi】参数获取,json和query
  • 深度学习02-pytorch-05-张量的索引操作
  • 2024 年最新前端ES-Module模块化、webpack打包工具详细教程(更新中)
  • Android 车载应用开发指南 - CarService 详解(下)
  • 在Spring Boot中实现多环境配置
  • 汽车总线之----FlexRay总线
  • LeetCode_sql_day31(1384.按年度列出销售总额)
  • C# 委托与事件 观察者模式
  • Java项目实战II基于Java+Spring Boot+MySQL的植物健康系统(开发文档+源码+数据库)
  • 设计模式之复合模式
  • 高级java每日一道面试题-2024年9月16日-框架篇-Spring MVC和Struts的区别是什么?
  • Redis发布和订阅
  • 波分技术基础 -- Liquid OTN技术特性
  • 高效打造知识图谱,使用LlamaIndex Relik实现实体关联和关系抽取
  • 火车站高铁站站点时刻查询网站计算机毕设/动车站点时刻查询
  • WebRTC编译后替换libwebrtc.aar时提示找不到libjingle_peerconnection_so.so库
  • 基于单片机控制的程控开关电源研究
  • list(一)
  • 基于微信小程序的健身房管理系统