Android笔试面试题AI答之Kotlin(6)
文章目录
- 24. 以下代码执行的结果是什么?
- 25. 解释一下下述Kotlin 代码有什么问题?
- 26. 如何在 Kotlin 中创建常量?
- 示例
- 注意事项
- 总结
- 27. Koltin 可以互换使用 IntArray 和 Kotlin 中的 Array 吗?
- IntArray
- Array<Int>
- 互换使用
- 从 IntArray 到 Array<Int>
- 从 Array<Int> 到 IntArray
- 结论
- 28. 阐述什么是 Kotlin double-bang (!!) 运算符?
- 使用场景
- 示例
- 注意事项
- 结论
24. 以下代码执行的结果是什么?
val aVar by lazy {
println("I am computing this value")
"Hola"
}
fun main(args: Array) {
println(aVar)
println(aVar)
}
这段代码的执行结果如下:
I am computing this value
Hola
Hola
这个结果的由来如下:
-
by lazy委托: 在 Kotlin 中,by lazy是一个委托属性,它用于延迟初始化。只有当第一次访问该属性时,才会执行其初始化块(即大括号中的代码),并将结果存储在属性中供后续访问。之后的所有访问都将直接返回存储的值,而不会再次执行初始化块。 -
初始化块: 在这个例子中,初始化块包含了一个
println调用和字符串"Hola"。当aVar第一次被访问时,会打印"I am computing this value"到控制台,并返回"Hola"。 -
main函数中的访问:- 第一次
println(aVar)调用时,aVar尚未被初始化,因此会执行其初始化块,打印"I am computing this value",并返回"Hola"。这个值随后被打印到控制台。 - 第二次
println(aVar)调用时,由于aVar已经被初始化(即它的值已经被存储在属性中),因此不会再次执行初始化块。相反,它直接返回之前存储的"Hola"值,并将其打印到控制台。
- 第一次
因此,尽管 aVar 被访问了两次,但初始化块只执行了一次,这就是为什么 "I am computing this value" 只打印了一次的原因。
25. 解释一下下述Kotlin 代码有什么问题?
class Student (var name: String) {
init() {
println("Student has got a name as $name")
}constructor(sectionName: String, var id: Int) this(sectionName) {
}
}
这段Kotlin代码中存在几个问题,主要涉及到构造函数的使用和语法错误。下面逐一解释:
-
构造函数重载和初始化顺序问题:
Kotlin中,构造函数可以使用constructor关键字来显式声明,但这并不是必需的,因为Kotlin通过主构造函数和次构造函数的概念来处理构造函数重载。在您的代码中,您尝试重载构造函数,但方式不正确。主构造函数是类头直接定义的构造函数(如
class Student(var name: String)),它直接初始化属性。次构造函数使用constructor关键字(虽然这不是必需的,通常通过其他构造函数委托来实现)或直接在类体内定义,并使用this(...)来调用另一个构造函数。问题在于,您的次构造函数尝试通过
this(sectionName)来调用主构造函数,但主构造函数需要一个String类型的参数,而您传递的是String类型的sectionName。这本身在类型上是匹配的,但逻辑上是不合理的,因为name和sectionName应该是不同的属性。 -
属性类型和作用域问题:
在次构造函数中,您声明了var id: Int,但这实际上是在构造函数的作用域内声明了一个局部变量,而不是类的属性。如果您想让id成为类的属性,它应该在类头中声明。 -
构造函数的正确重载:
如果您想要一个额外的构造函数来同时接收sectionName和id,并且仍然保持name属性(可能是可选的或默认的),您应该这样做:class Student(var name: String) {var id: Int? = null // 假设id是可选的init {println("Student has got a name as $name")}constructor(sectionName: String, id: Int) : this("") { // 假设name有一个默认值,如空字符串this.id = idprintln("Student is in section $sectionName")} }注意,这里我使用了
: this("")来调用主构造函数,并传递了一个默认的name值(这里是空字符串)。然后,在次构造函数内部,我设置了id的值,并打印了sectionName。但是,请注意,这种设计可能不是最佳的,因为它强制所有Student实例都有一个默认的名称,这可能不是您想要的。更好的方法是,如果
name是必需的,您应该让主构造函数保持其原始形式,并通过其他方式(如工厂方法或构建器模式)来创建具有额外属性的Student实例。 -
语法和逻辑错误:
在您的原始代码中,次构造函数的定义方式(使用constructor关键字和var关键字在参数上)是语法上不正确的,并且在逻辑上也是不合理的。
综上所述,您需要重新考虑您的类设计,特别是如何处理构造函数之间的参数和属性初始化。
26. 如何在 Kotlin 中创建常量?
在 Kotlin 中,创建常量的方式与 Java 有所不同,因为 Kotlin 强调不可变性(immutability)和清晰性。Kotlin 使用 val 关键字来声明只读变量,这相当于 Java 中的 final 变量,但在 Kotlin 中更常被视作常量,因为一旦初始化后就不能被重新赋值。
示例
// 创建一个常量并初始化
val constantValue: Int = 10// 由于 constantValue 是用 val 声明的,以下尝试修改它的值将会导致编译错误
// constantValue = 20 // 这行代码会编译失败// 可以直接初始化而不需要显式指定类型(Kotlin 会自动推断)
val anotherConstant = "Hello, Kotlin!"// 对于对象类型的常量,Kotlin 仍然会确保你不能再指向另一个对象,但对象内部的状态仍然可以是可变的
val mutableList = mutableListOf(1, 2, 3)
// mutableList = mutableListOf(4, 5, 6) // 这会编译失败,因为 mutableList 是 val
// 但你可以修改列表的内容
mutableList.add(4)
注意事项
- 使用
val声明的变量必须在声明时初始化,或者通过构造器初始化(在类的构造器内初始化)。 - 虽然 Kotlin 中的
val变量通常被视为常量,但它们的“常量性”仅限于引用不变。如果你将val变量声明为可变集合(如MutableList),则你仍然可以修改集合的内容,但不能将val变量重新指向另一个集合。 - 对于需要确保不可变性的场景(例如,集合的内容也不可变),你可能需要使用 Kotlin 标准库中的不可变集合类型(如
listOf、setOf、mapOf等),或者使用第三方库来提供更深层次的不可变性保证。
总结
在 Kotlin 中,val 关键字用于创建常量,即一旦初始化后就不能重新赋值的变量。虽然 Kotlin 的类型系统不直接提供“真正的”常量(如 C/C++ 中的 #define 或 Java 中的 static final 原始类型常量),但 val 提供了强大的不可变性保证,并且 Kotlin 的类型推断和集合框架使得在大多数情况下,这种差异是无关紧要的。
27. Koltin 可以互换使用 IntArray 和 Kotlin 中的 Array 吗?
在 Kotlin 中,IntArray 和 Array<Int> 是两种不同的类型,它们之间不能直接互换使用,但你可以通过一些转换操作来在它们之间转换数据。
IntArray
IntArray 是 Kotlin 中的一个原生数组类型,专门用于存储 Int 类型的元素。它是 Java 中 int[] 类型的直接对应物,在 Kotlin 中被封装为一个类,提供了更多的方法和属性,但仍然是固定大小的。
Array
Array<Int> 是 Kotlin 中的泛型数组,可以存储 Int 类型的元素。与 IntArray 不同,Array<Int> 是通过 Kotlin 的泛型数组工厂方法创建的,如 arrayOf() 或 Array(size: Int, init: (Int) -> T)。Array<Int> 提供了更多的灵活性和与 Kotlin 集合框架的互操作性,但它不是原生类型,因此可能在某些情况下性能略逊于 IntArray。
互换使用
由于 IntArray 和 Array<Int> 是不同的类型,你不能直接将一个 IntArray 赋值给一个 Array<Int> 变量,反之亦然。但是,你可以通过遍历数组并复制元素来在它们之间转换数据。
从 IntArray 到 Array
val intArray = intArrayOf(1, 2, 3)
val array: Array<Int> = intArray.map { it }.toTypedArray()
这里使用了 map 函数来遍历 IntArray 中的每个元素,并创建一个新的 List<Int>,然后通过 toTypedArray() 方法将其转换为 Array<Int>。
从 Array 到 IntArray
val array: Array<Int> = arrayOf(1, 2, 3)
val intArray = IntArray(array.size) { array[it] }
这里使用了 IntArray 的构造函数,它接受一个大小和一个 lambda 表达式,该表达式用于初始化数组中的每个元素。在这个例子中,lambda 表达式简单地返回了 array 中对应索引的元素。
结论
虽然 IntArray 和 Array<Int> 在 Kotlin 中都用于存储整数数组,但它们是不同的类型,不能直接互换使用。但是,你可以通过简单的转换操作在它们之间转换数据。选择哪种类型取决于你的具体需求,比如性能考虑(IntArray 可能更快)或与其他 Kotlin 集合的互操作性(Array<Int> 可能更方便)。
28. 阐述什么是 Kotlin double-bang (!!) 运算符?
Kotlin 中的 double-bang (!!) 运算符是一个非空断言运算符(Non-null assertion operator)。它的主要作用是显式地告诉 Kotlin 编译器某个变量或对象在当前的上下文中不应该为 null,即使它在类型声明时是可空的(即类型后面跟有 ?)。
使用场景
当你确定某个变量或对象在特定情况下一定不为 null,但 Kotlin 编译器由于类型信息不足或代码结构复杂而无法自动推断出这一点时,你可以使用 !! 运算符来强制编译器接受这一断言。然而,使用 !! 运算符需要谨慎,因为如果变量或对象实际上为 null,那么程序会在运行时抛出 NullPointerException。
示例
假设你有一个可空的字符串变量 var text: String?,并且你确信在某个特定的代码块中 text 一定不为 null,但你需要调用它的 length 属性。由于 text 是可空的,直接调用 text.length 会导致编译错误,因为 Kotlin 的空安全特性要求你必须处理 null 的情况。此时,你可以使用 !! 运算符来断言 text 不为 null:
val length = text!!.length
如果 text 在这里确实不为 null,那么这段代码将正常工作。然而,如果 text 是 null,那么程序将在执行到这一行时抛出 NullPointerException。
注意事项
- 谨慎使用:由于
!!运算符可能导致运行时异常,因此应该谨慎使用。在可能的情况下,使用 Kotlin 的空安全特性(如安全调用运算符?.和 Elvis 运算符?:)来避免使用!!。 - 替代方案:
- 安全调用运算符 (
?.):当对象可能为null时,使用它来安全地访问对象的属性或方法。如果对象为null,则整个表达式的结果为null,而不会抛出异常。 - Elvis 运算符 (
?:):当需要为可能为null的表达式提供一个默认值时,使用它。如果左侧表达式的结果为null,则整个表达式的结果为右侧的默认值。
- 安全调用运算符 (
结论
Kotlin 的 double-bang (!!) 运算符是一个非空断言运算符,用于在特定情况下断言变量或对象不为 null。然而,由于它可能导致运行时异常,因此应该谨慎使用,并尽可能寻找更安全的替代方案。
答案来自文心一言,仅供参考
相关文章:
Android笔试面试题AI答之Kotlin(6)
文章目录 24. 以下代码执行的结果是什么?25. 解释一下下述Kotlin 代码有什么问题?26. 如何在 Kotlin 中创建常量?示例注意事项总结 27. Koltin 可以互换使用 IntArray 和 Kotlin 中的 Array 吗?IntArrayArray<Int>互换使用从…...
“tcp控制协议”的理解
情景解释: 1.过程: 在用户进行网络间通信时,不管是客户端还是服务端,都会有两个缓冲区——发送缓冲区和接受缓冲区。 通过4个缓冲区进行数据交流。 用户通过write()将数据发送到他的发送缓冲区中,再传输到服务端的…...
考试成绩查询系统,发成绩不再愁
在考试季落幕后,家长们总是怀着紧张的心情,期待着孩子们的成绩单。传统上,老师们需要手动发送成绩单给每位家长,这个过程不仅耗时耗力,而且容易出错,给老师们带来了不小的压力。 随着科技的进步,…...
【扒代码】图像数据 Transformer
def forward(self, x, bboxes):# 确定对象的数量,如果不是零样本学习场景,则根据bboxes的数量确定num_objects bboxes.size(1) if not self.zero_shot else self.num_objects# backbone# 通过主干网络提取特征backbone_features self.backbone(x)# pre…...
光伏仿真系统的使用流程
为了更有效地规划设计并评估光伏电站的性能与经济性,光伏仿真系统应运而生。该系统通过模拟实际运行场景,为项目开发者提供全面的数据支持和决策依据。 1、气象数据分析 气象数据是光伏系统性能评估的基础。此阶段,仿真系统需收集并处理项目…...
【Dash】使用 dash_mantine_components 创建图表
一、Styling Your App The examples in the previous section used Dash HTML Components to build a simple app layout, but you can style your app to look more professional. This section will give a brief overview of the multiple tools that you can use to enhan…...
Unity 输入模块 之 初识新输入系统(其实也不新)
本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正 1.介绍 当年的宣传网页Unity新一代输入系统介绍 - 技术专栏 - Unity官方开发者社区 老输入系统每次配置新项目都需要写…...
springboot+redis集群实现集群拓扑动态刷新温故
springboot项目,并集成redis集群,当redis集群节点宕掉后又恢复了,但springboot调用redis集群服务报错,下面对springboot集成redis集群实现集群拓扑动态刷新进行温习和巩固。 原因分析: 使用lettuce连接redis集群实例&a…...
LoadRunner常用函数介绍
内置函数和Jmeter差不多,Jmeter更火,更好百度,毕竟开源,用的人多,所以有些函数如果不太懂用法,可以百度Jmeter作为参考来使用LR。 脚本中常用函数 事务组 lr_start_transaction("KaiShi"); //…...
通讯录管理系统
目录 一. 实验目的 二. 系统设计 三. 系统设计流程: 四. 实验结果及效果展示 五. 实验总结 六. 附录:源代码 一. 实验目的 本次实验旨在通过实现一个简单的通讯录管理系统,加深对C语言结构体、数组、指针、函数、控制结构等基本概念的理…...
基于Python爬虫+机器学习的长沙市租房价格预测研究
🤵♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞Ǵ…...
开发效率翻倍攻略!大学生电脑小白管理秘籍,资料秒搜技巧大公开!C盘满了怎么办?如何快速安全的清理C盘?烦人的电脑问题?一键解决!
如何正确管理自己的第一台电脑?大一新生如何管理自己的电脑?老鸟如何追求快捷操作电脑? 文章目录 如何正确管理自己的第一台电脑?大一新生如何管理自己的电脑?老鸟如何追求快捷操作电脑?前言初级基础分区操…...
[C#数据加密]——MD5、SHA、AES、RSA
一、C#数据加密介绍 数据加密是信息安全领域的一个重要组成部分,它用于保护数据不被未授权访问。以下是一些常见的加密算法和方法: 1、MD5 (Message Digest Algorithm 5): 一种广泛使用的哈希函数,可以产生128位的哈希值。通常用于验证文件完…...
QT不阻塞UI的方式
方法1:QtConcurrent #include <QtConcurrent> #include <QFuture> #include <QFutureWatcher> #include <QDebug>void longRunningTask() {// 模拟耗时操作QThread::sleep(5); }void startTask() {QFuture<void> future QtConcurre…...
鸿蒙HarmonyOS开发:常用布局及实用技巧
文章目录 一、概述二、盒子模型三、线性布局(Column/Row)1、space属性2、justifyContent属性3、alignItems属性 四、实用技巧1、Blank组件的使用2、layoutWeight属性的使用 一、概述 布局是指对页面组件进行排列和定位的过程,其目的是有效地…...
【解答】洛必达法则的使用条件及常见错误,洛必达法则的适用条件,常见的易错点,2022数一第一题例题
目录 洛必达法则的使用条件及常见错误 洛必达法则的适用条件 常见的易错点 举例说明(见D选项) 总结 🌈 嗨,我是命运之光! 🌌 2024,每日百字,记录时光,感谢有你&…...
使用Python下载飞书共享表格数据教程
写在前面 随着企业协作办公软件的流行,飞书以其高效的协作能力和便捷的共享功能,成为了许多公司必备的工具之一。在日常工作中,我们经常需要从飞书中下载共享的表格数据进行分析。本文将详细介绍如何使用Python下载飞书共享表格数据。 前置…...
【C++】protobuf的简单使用(通讯录例子)
protobuf的简单使用(通讯录例子) .proto文件的编写保留字段字段唯一编号protobuf的类型enum类型Any类型oneof类型map类型完整通讯录代码.proto文件write文件read文件运行结果 .proto文件的编写 syntax用于指定protobuf的语法;package当.prot…...
Apple 智能基础语言模型
Introducing Apple’s On-Device and Server Foundation Models technical details June 10, 2024 在2024年的全球开发者大会上,苹果推出了Apple Intelligence,这是一个深度集成到iOS 18、iPadOS 18和macOS Sequoia中的个人智能系统。Apple Intelligen…...
GreptimeDB融资数百万美元; Oracle提供免费长期MySQL; 谷歌大模型支持云数据库问题洞察
重要更新 1. 开源时序数据库 GreptimeDB宣布完成数百万美元的新一轮融资。GreptimeDB是一款Rust 语言编写的时序数据库,具有分布式,开源,云原生,兼容性强等特点,帮助企业实时读写、处理和分析时序数据的同时࿰…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
[特殊字符] 手撸 Redis 互斥锁那些坑
📖 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作,想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁,也顺便跟 Redisson 的 RLock 机制对比了下,记录一波,别踩我踩过…...
