常见Kotlin高频问题解惑

在笔者的Kotlin交流群里,不少同学反复遇到了一些相似的问题。这些问题大都比较基础,但又容易产生误解。因此,我决定写一篇文章,整理群里同学遇到的一些问题

变量和常量的使用

在Kotlin语言中,我们使用var声明变量,使用val声明常量。由于来自Java语言中没有区分常量变量的影响,一些同学对这两个关键字的理解有问题。为了理解这两个变量的区别,我们可以用两个等式来说明一下:

var str: String = "abc"  => public String str = "abc"val str: String = "abc" => public final String str = "abc"
复制代码

=>符号后面是对应的Java代码,Java语言使用final关键字声明常量。很明显,使用明确的变量和常量声明更有助于理解。

注:一些Java程序员很少使用final关键字,这说明这部分同学对于常量的使用不太理解。事实上,JVM中有一个常量池,如果发现常量池中存在该值就直接使用;反之,则创建并存入常量池。从这个层面来说,使用常量比使用变量效率更高。更重要的是,如果你声明一个不会被改动的变量,使用final修饰将更准确,也更安全。

lateinit

其实,在使用Kotlin语言的这两年里,我从来没有用过这个关键词。但刚刚接触Kotlin语言的同学似乎很喜欢使用这个修饰符修饰变量。

这个关键词是做什么的呢?这很有意思!

在Kotlin语言中,我们必须严格区分可选值和非可选值。而无论是可选值还是非可选值,在声明的时候你都必须首先初始化。

那么,如果本身是一个非可选值,但在初始化的时候我们并不知道应该赋什么初始值。或者说,我们压根就不想赋初始值,该怎么办?lateinit就是用于解决这个问题的。

其实这个场景的确广泛存在,比如这个变量是一个对象类型的数据。很明显,给一个对象变量赋予一个初始值的意义不大。因此,你可以选择使用lateinit修饰这个变量。可是,与此同时,你的灾难也降临了!

群里同学反馈多次的一个问题就是:提示变量没有初始化。

其实,本身这个问题并不难,但难的是你要完全弄清楚使用lateinit的前提。如果你决定使用lateinit,你至少应该记住下面两个规则:

  1. lateinit只能用于修饰非可选值。因此,必须确保你的这个变量在任何时候都不会被赋值为空。
  2. lateinit表示这个变量的初始化可能发生在任何时候。因此。使用lateinit之前,问一问自己。你是否非常清楚你一定会在使用这个变量之前将其进行初始化。

为了避免因为未初始化引起的异常问题,Kotlin语言为每一个lateini属性实例提供了一个判断是否已经初始化的属性值isInitialized。因此,为了避免出现初始化问题,你最好判断一下这个变量是否已经完成初始化:

private lateinit var dog: Dog
if (::dog.isInitialized) {....
}
复制代码

非可选值中的空指针陷阱

部分同学喜欢这样声明数据类:

data class Ticket(var id: Long, var name: String ...) 
复制代码

对于客户端类应用,数据类通常对应后台返回的一段Json字符串。那么,悲剧又诞生了!如果后台没有返回name字段,Json框架在进行数据解析的时候认为name为空值,尝试将其赋值为空。不可预料地,臭名昭著的空指针异常又出现了。

因此,记住一个原则:除非你确定这个变量一定不会被赋值为空。否则,请尽量使用可选值。

可选值中的空指针陷阱

类似地,在可选值中也存在着空指针陷阱。而因为受到Java语言的影响,这个部分出现空指针异常的概率更高。看下面的例子:

var isRight: Boolean? = nullif (isRight!!) {...
}
复制代码

对于上面的代码,Kotlin将毫不留情地抛给你一个空指针异常。比Java空指针异常更温柔的是,这个空指针异常的名称叫做KotlinNullPointerException

因此,记住一个原则,如果使用可选值需要进行解包的时候。一定要确定这个可选值此刻是有值的。针对上面这个例子,更好的处理方式应该是这样:

var isRight: Boolean? = nullif (isRight ?: false) {...
}
复制代码

不要误会,我没有基本数据类型

Kotlin认为所谓的基本数据类型,所谓的拆包,封包是没有意义的。因此,在Kotlin语言中所有的基本数据类型变量也是对象,拥有与变量一样的行为。

所以,记住一个原则,从Java转换到Kotlin,在使用基本数据类型变量的时候同样需要注意合理地选择可选值和非可选值,慎用lateinit。

双冒号到底是个什么东西

双冒号(::)操作符是Kotlin语言特有的操作符。它主要有以下几个作用:

  1. 获取KClass引用
  2. 获取函数引用
  3. 获取属性引用
  4. 获取构造函数引用

获取KClass引用

这是很常用的表达式,不过通常用于获取java的Class实例:

val javaClass = Person::class.java
复制代码

注:这在Android开发中比较常用,通常用于获取Activity的Java class实例。

获取函数引用

在Kotlin语言中,你可以使用函数作为某个高阶函数的参数。使用双冒号操作符可以用于获取具体的函数引用作为参数传入目标函数:

fun cdn(x: Int): Boolean {return x >= 3
}fun filter(x: Int, condition: (x: Int)->Boolean): Boolean {return condition(x)
}filter(5, ::cdn)
复制代码

获取属性引用

Kotlin类中每一个成员变量对应一个Property实例,使用双冒号操作符可以用于获取该属性实例。在lateinit场景中,这很有用!

class Dog {var name: String? = null
}
// 注意:这里获取的是Property实例,而非属性本身
val property = Dog::nameval receiver = Dog()
println(property.get(receiver))
复制代码

注:类对象变量本身并没有isInitialized属性,要判断lateinit变量是否已经完成初始化,需要通过双冒号获取该变量对应的Property实例才能判断。

获取构造函数引用

双冒号操作符也可以用于获取某个对象的构造函数实例,具体的用法是:在类名称前面使用双冒号。看下面的例子:

class Dog {var name: String? = null
}val init = ::Dog
val dog = init()
println(dog.name)
复制代码

注:该构造函数实例同样可以作为参数传入某个高阶函数中。

PS:双冒号操作符其实就是用于简化Kotlin反射而创造的一种操作符。

简单总结

你在日常使用Kotlin语言的过程中还有遇到其它问题吗?如果有,请留言告诉我!

欢迎加入Kotlin交流群

如果你也喜欢Kotlin语言,欢迎加入我的Kotlin交流群: 329673958 ,一起来参与Kotlin语言的推广工作。

编程,我们是认真的!

关注欧阳锋工作室,与欧阳锋同行!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/278109.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于神经网络训练的一些建议笔记

关于网络训练时的参考建议: 1.train loss不断下降,test loss不断下降,网络正在学习 2.train loss不断下降,test loss趋于不变,网络过拟合,需要增大数据;减小网络规模dropout;权重衰减…

Microsoft Teams的保留策略

Microsoft Teams保留策略现在可在Office 365安全性和合规性中心里进行配置 今天,我们很自豪地宣布,我们正在开始推出针对Microsoft Teams的保留策略。 推出预计将在未来几周内完成。 通过此次发布,Teams管理员可以使用Office 365安全性和合规…

八年溯源,如何巧搭区块链

虎嗅注:区块链正在逐步商业化,但最大的挑战是共识。 为什么这样说?因为商品的溯源防伪业务在过去正是因为缺乏信任感而没有得到普及,这是每个溯源从业者最大的感受。 在虎嗅虎跑团每两周一次线上分享会上,溯源链创始人…

数字签名过程及数字证书

数字签名是什么? 作者:David Youd 翻译:阮一峰 原文网址:http://www.youdzone.com/signature.html 1.鲍勃有两把钥匙,一把是公钥,另一把是私钥。 2.Bob把公钥送给他的朋友们-Pat、Doug、Susan-- 每人一把…

Teams与OneDrive for Business和SharePoint的关系

作为一个相对看重个人信息安全与隐私的人,个人附件等资料在Microsoft Teams中的存储方式、文件访问权限、可见范围问题引起了我的好奇。 众所周知,Teams包含3大主要的模块:单人聊天、团队、会议。那下面让我们一起来看一下,对这三…

hadoop学习笔记(二):centos7三节点安装hadoop2.7.0

环境win7vamvare10centos7 一、新建三台centos7 64位的虚拟机 master 192.168.137.100 root/123456 node1 192.168.137.101 root/123456 node2 192.168.137.102 root/123456 二、关闭三台虚拟机的防火墙,在每台虚拟机里面执行: systemctl sto…

index.html 的默认301或者302跳转

index.html 的默认301或者302跳转 <!DOCTYPE html> <html> <head> <title>Google</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> <script>window.locat…

在Microsoft Teams中的Visio协作

所有Team站点都带有专用文件库&#xff0c;用于存储所有工作组的内容。 您现在可以从桌面或云存储站点将Visio文件上载到此库&#xff0c;例如&#xff0c;您所在Team的资产都集中在一个位置&#xff0c;供具有权限的任何人进行访问。与其他存储文件一样&#xff0c;您可以直接…

用区块链打击假新闻 这可能是最2017年的一件事

据外媒报道&#xff0c;非营利性基金会PUBLIQ公布了一个基于区块链打造的平台。这是一个用于创建和分享原创新闻和媒体内容的平台&#xff0c;它将在近期推出。据了解&#xff0c;PUBLIQ创建这一平台则是希望能借用类似于比特币一样的系统来打击假新闻。 通过创建一个受信任的经…

oo面向对象第一单元总结

oo第一次作业主要考察了多项式的求导&#xff0c;从简单的幂函数求导到三角函数求导再到嵌套函数的求导&#xff0c;难度循序渐进&#xff0c;对我们对于面向对象的理解的要求也在一次一次提升。一行行代码打下来&#xff0c;一夜夜熬过去&#xff0c;我也来到了这个短暂的停靠…

Microsoft Teams免费版本初体验

Microsoft Teams推出有一段时间了&#xff0c;如果想要体验Teams&#xff0c;必须需要有Office365的订阅。最近微软为了进一步推广Teams&#xff0c;突然宣布Teams免费了。使用过Teams的读者知道Teams是基于Office365账号和组的&#xff0c;那它免费后&#xff0c;不使用Office…

JS:封装函数判断数据类型

思路 1 ).根据 typeof() 的返回值将数据分为2种情况 a.返回值为 string number boolean undefined function (直接返回 typeof() 的返回值) b.返回值为object 2 ).再将 typeof() 返回值为 object 的数据分为2种情况 a.null (直接返回自身) b.包装类 对象 数组 (再进行细分) var…

强制禁用gitlab的双因子认证:Two-Factor Authentication

&#xff08;一&#xff09;问题描述&#xff1a; 此博客解决如下问题&#xff1a;禁用gitlab的双因子认证 禁用前&#xff0c;如图&#xff08;此时&#xff0c;你在gitlab中什么也干不了&#xff09; &#xff08;二&#xff09;思路分析&#xff1a; 百度了很多方法&#xf…

如何将Outgoing Webhook部署到中国版Azure

在这篇文章中&#xff0c;我们主要来如何将Azure DevOps中的项目作为应用发布到中国版Azure的App Service中。 什么是Azure DevOps Azure DevOps, 原名为VSTS, 全称是Visual Studio Team System&#xff0c;是由微软开发的一套具有高生产力、高集成性、可扩展的生命周期开发工…

Google SRE 读书笔记 扒一扒SRE用的那些工具

写在前面 最近花了一点时间阅读了《SRE Goolge运维解密》这本书&#xff0c;对于书的内容大家可以看看豆瓣上的介绍。总体而言&#xff0c;这本书是首次比较系统的披露Google内部SRE运作的一些指导思想、实践以及相关的问题&#xff0c;对于我们运维乃至开发人员都有一定的借鉴…

第8章 java中的并发工具类

8.1 等待线程完成的CountDownLatch 作用&#xff1a;让一个线程等待其余线程完成之后在继续执行&#xff0c;如主线程等待开启服务的子线程执行完毕后主线程继续执行&#xff0c;类似于join。 转载于:https://www.cnblogs.com/AshOfTime/p/10608910.html

Microsoft Teams的Meet Now功能

今天&#xff0c;我们宣布完成了Skype for Business to Teams路线图中首次披露的几项关键会议功能。当个人联系&#xff0c;沟通和协作时&#xff0c;工作就自然而然的完成了&#xff0c;我们相信这些功能&#xff08;除了我们2月的公告之外&#xff09;使Microsoft Teams为所有…

深入 Adobe Reader 保护模式 —— 第一部分 —— 设计

原作者&#xff1a;Liz McQuarrie, Ashutosh Mehra, Suchit Mishra, Kyle Randolph, Ben Roger 译者&#xff1a;lordVice 校对&#xff1a; StrokMitream 看雪翻译小组 介绍 我是 Kyle Randolph&#xff0c; 和我一起的还有负责 Acrobat 系列产品的安全团队&#xff0c; 这些产…

Java泛型主题讨论

说明&#xff1a;在学习泛型这一知识点中&#xff0c;主要参考自《疯狂Java讲义》第7章P307-P330的泛型内容&#xff0c;因为是跳着阅读&#xff0c;所以前面的一些名词不是特别清楚&#xff0c;这里也做出适当备注&#xff0c;供自己识记与理解。 1.泛型 理解&#xff1a;说到…

初学Vue.js,从头来过~

之前上课也学过vue.js&#xff0c;但是一遍过下来&#xff0c;实话&#xff0c;没有记住什么&#xff0c;所以决定自己在对照着文档过一遍&#xff0c;所以之后会弄一些基础的东西&#xff0c;还请大神们莫喷~~~~今天先给平台打一个预防针&#xff0c;Young C 要来啦~~ 吼吼&…