关键词:
【中文标题】?: 在 Kotlin 中做啥? (猫王操作员)【英文标题】:What does ?: do in Kotlin? (Elvis Operator)?: 在 Kotlin 中做什么? (猫王操作员) 【发布时间】:2018-06-23 12:00:54 【问题描述】:我不知道?:
在这种情况下做了什么
val list = mutableList ?: mutableListOf()
为什么可以修改成这个
val list = if (mutableList != null) mutableList else mutableListOf()
【问题讨论】:
如果不为空则返回左侧,否则返回右侧。第一个表达式是第二个表达式的简写。 kotlinlang.org/docs/reference/null-safety.html#elvis-operator 【参考方案1】:TL;DR:如果结果对象引用 [第一个操作数] 不是 null
,则返回它。否则返回第二个操作数(可能是null
)的值。另外,如果返回null,操作符可以抛出异常。
Elvis 运算符 是许多编程语言的一部分,例如Kotlin 还有 Groovy 或 C#。 我发现Wikipedia 的定义非常准确:
在某些计算机编程语言中,Elvis 运算符
?:
是一个二元运算符,如果该操作数是true
,则返回其第一个操作数,否则计算和返回它的第二个操作数。它是一种三元条件运算符的变体,? :
,在这些语言(以及许多其他语言)中都可以找到:Elvis 运算符是 省略了第二个操作数的三元运算符 .
对于 Kotlin 来说尤其如此:
一些计算机编程语言对该运算符有不同的语义。 不是第一个操作数必须产生一个布尔值,它必须产生一个对象引用。如果结果对象引用不是
null
,则返回它。否则返回第二个操作数的值(可能是null
)。如果第二个操作数为 null,则操作符也可以抛出异常。
一个例子:
x ?: y // yields `x` if `x` is not null, `y` otherwise.
x ?: throw SomeException() // yields `x` if `x` is not null, throws SomeException otherwise
【讨论】:
【参考方案2】:Elvis Operator 由一个问号后跟一个冒号表示:?:
,它可以与以下语法一起使用:
first operand ?: second operand
它使您可以编写简洁的代码,并且可以这样工作:
如果first operand
不为空,则返回。如果为空,则返回second operand
。这可用于保证表达式不会返回 null 值,因为如果提供的值为 null,您将提供一个不可为 null 的值。
例如(在 Kotlin 中):
fun retrieveString(): String //Notice that this type isn't nullable
val nullableVariable: String? = getPotentialNull() //This variable may be null
return nullableVariable ?: "Secondary Not-Null String"
这种情况下,如果getPotentialNull
的计算值不为null,则由retrieveString
返回;如果为null,则返回第二个表达式"Secondary Not-Null String"
。
另请注意,如果左侧为 null,则仅评估右侧表达式。
在 Kotlin 中,您可以使用任何表达式作为 second operand
,例如 throw Exception
表达式
return nullVariable ?: throw IllegalResponseException("My inner function returned null! Oh no!")
Elvis Operator 这个名字来源于美国著名歌手Elvis Presley。他的发型像一个问号
资料来源:Wojda、I. Moskala、M. 使用 Kotlin 进行 Android 开发。 2017. Packt 出版
【讨论】:
【参考方案3】:这被称为Elvis operator,它确实......正是您在问题中所描述的。如果它的左侧是 null
值,则它返回右侧,有点作为后备。否则它只返回左侧的值。
a ?: b
只是if (a != null) a else b
的简写。
更多类型的例子:
val x: String? = "foo"
val y: String = x ?: "bar" // "foo", because x was non-null
val a: String? = null
val b: String = a ?: "bar" // "bar", because a was null
【讨论】:
如果你来自java,它更像是:a != null ? a : b
【参考方案4】:
我们来看看defintion:
当我们有一个可为空的引用 r 时,我们可以说“如果 r 不为空,使用 它,否则使用一些非空值 x":
?:
(Elvis) 运算符避免冗长,使您的代码非常简洁。
例如,许多集合扩展函数返回 null
作为后备。
listOf(1, 2, 3).firstOrNull it == 4 ?: throw IllegalStateException("Ups")
?:
为您提供了一种优雅地处理后备情况的方法,即使您有多层后备。如果是这样,您可以简单地链接乘法 Elvis 运算符,如下所示:
val l = listOf(1, 2, 3)
val x = l.firstOrNull it == 4 ?: l.firstOrNull it == 5 ?: throw IllegalStateException("Ups")
如果你用 if else 来表达同样的意思,那将是更多难以阅读的代码。
【讨论】:
【参考方案5】:简单地说,你有两只手。你想知道,你的左手现在还在工作吗?如果左手不工作,return
empty
否则busy
Java 示例:
private int a;
if(a != null)
println("a is not null, Value is: "+a)
else
println("a is null")
Kotlin 示例:
val a : Int = 5
val l : Int = if (a != null) a.length else "a is null"
【讨论】:
【参考方案6】:Kotlin 中的 elvis 运算符用于 null 安全性。
x = a ?: b
在上面的代码中,如果 a 不是 null
和 b
如果 a
是 null
,x
将被分配 a
的值。
不使用 elvis 运算符的等效 kotlin 代码如下:
x = if(a == null) b else a
【讨论】:
【参考方案7】:基本上,如果 Elvis 的左侧由于某种原因返回 null,则改为返回右侧。
即
val number: Int? = null
println(number ?: "Number is null")
所以,如果数字不为空,它将打印数字,否则将打印“数字为空”。
【讨论】:
【参考方案8】:不过是一点点补充
X = A ?: B
如果A
和B
的计算结果都为null
,X
仍将是null
因此,如果您希望 X
始终为 non-null
,请确保 B
始终为 non-null
,或者如果 B
是函数或表达式,则始终计算为 non-null
。
【讨论】:
【参考方案9】:考虑下面的例子,
var myStr:String? = null
//trying to find out length of myStr, but it could be null, so a null check can be put as,
val len = if (myStr != null)
myStr.length
else
-1
使用elvis操作符,上面的代码可以写成一行
val len = myStr?.length ?: -1 // will return -1 if myStr is null else will return length
【讨论】:
【参考方案10】:除了已经满足的内容之外,还有一种对我来说并不明显但很常见的好模式,例如您正在编写一个长函数,但如果某些内容为 null,则继续没有意义,您唯一能做的就是从该函数返回。通常你会写
something = expression
if (something == null)
return
有了猫王,它变得更短更优雅:
something = expression ?: return
【讨论】:
:: 在 PostgreSQL 中做啥? [复制]
】::在PostgreSQL中做啥?[复制]【英文标题】:Whatdoes::doinPostgreSQL?[duplicate]::在PostgreSQL中做什么?[复制]【发布时间】:2013-03-1009:12:04【问题描述】:我在网上看到过很多涉及postgres代码的地方::。例如:SELECT\'apple,cherryapple,avocado\'::... 查看详情
是啥! (感叹号)在 FreeMarker 中做啥?
】是啥!(感叹号)在FreeMarker中做啥?【英文标题】:Whatdoesthe!(exclamationpoint)inFreeMarkerdo?是什么!(感叹号)在FreeMarker中做什么?【发布时间】:2020-05-0322:54:02【问题描述】:我一直在Magnoliacodeexamples的FreeMarker代码末尾看到感... 查看详情
|=(管道等号)符号在python中做啥?
】|=(管道等号)符号在python中做啥?【英文标题】:Whatdoes|=(pipeequal)signdoinpython?|=(管道等号)符号在python中做什么?【发布时间】:2017-03-0808:10:34【问题描述】:我在一个项目中看到一段代码,其中写了以下内容:move=Move.crea... 查看详情
<!-- 在Javascript中做啥?
】<!--在Javascript中做啥?【英文标题】:whatdoes<!--inJavascriptdo?<!--在Javascript中做什么?【发布时间】:2011-08-2109:56:31【问题描述】:在谷歌中搜索符号太难了,所以我在这里问。<!--对我来说看起来像是一条评论,但它... 查看详情
3D 在这个 HTML 中做啥?
】3D在这个HTML中做啥?【英文标题】:What\'sa3DdoinginthisHTML?3D在这个HTML中做什么?【发布时间】:2011-04-3006:52:30【问题描述】:我正在尝试通过查看其代码来复制我进入我的gmail的邮件。我在多个源查看器中看到了很多这种情况... 查看详情
compute() 在 dask 中做啥?
】compute()在dask中做啥?【英文标题】:whatdoescompute()doindask?compute()在dask中做什么?【发布时间】:2019-11-0514:01:13【问题描述】:我是dask的新手,不明白compute()方法在dask中究竟做了什么?它是一种打印它调用的对象的方法吗?我... 查看详情
“|”是啥意思(单管道)在 JavaScript 中做啥?
】“|”是啥意思(单管道)在JavaScript中做啥?【英文标题】:Whatdoesthe"|"(singlepipe)doinJavaScript?“|”是什么意思(单管道)在JavaScript中做什么?【发布时间】:2011-09-0521:37:33【问题描述】:console.log(0.5|0);//0console.log(-1|0);/... 查看详情
您可以在 CoreBluetooth 后台委托调用中做啥?
】您可以在CoreBluetooth后台委托调用中做啥?【英文标题】:WhatcanyoudoinCoreBluetoothbackgrounddelegatecalls?您可以在CoreBluetooth后台委托调用中做什么?【发布时间】:2013-01-0910:56:40【问题描述】:我在我的项目中使用CoreBluetooth。我已经... 查看详情
>> 在 Java 中做啥?
】>>在Java中做啥?【英文标题】:Whatdoes>>doinJava?>>在Java中做什么?【发布时间】:2011-04-2416:24:07【问题描述】:好的,我尝试查找>>或shift的含义,但正如本网站所解释的那样,这让我无法理解:http://www.... 查看详情
++ 运算符在 Python 中做啥? [复制]
】++运算符在Python中做啥?[复制]【英文标题】:Whatis++operatordoinginPython?[duplicate]++运算符在Python中做什么?[复制]【发布时间】:2013-11-0301:56:42【问题描述】:Python不支持C风格的++a增量,但令我惊讶的是,它并没有抱怨导致我暂... 查看详情
??!??! 是啥意思?运算符在 C 中做啥?
】??!??!是啥意思?运算符在C中做啥?【英文标题】:Whatdoesthe??!??!operatordoinC???!??!是什么意思?运算符在C中做什么?【发布时间】:2011-12-1102:56:28【问题描述】:我看到一行C看起来像这样:!ErrorHasOccured()??!??!HandleError();它编译正... 查看详情
“?”是啥意思?和“:”在布尔语句中做啥? [复制]
】“?”是啥意思?和“:”在布尔语句中做啥?[复制]【英文标题】:Whatdoes"?"and":"doinbooleanstatements?[duplicate]“?”是什么意思?和“:”在布尔语句中做什么?[复制]【发布时间】:2013-05-3009:47:19【问题描述】... 查看详情
">"在Css中做啥[重复]
】">"在Css中做啥[重复]【英文标题】:Whatis">"doinginCss[duplicate]">"在Css中做什么[重复]【发布时间】:2014-06-0414:32:28【问题描述】:我有一个关于css的问题,在一些引导文件中我看到">":.nav-tabs.nav-jus... 查看详情
我应该在 CMakeLists.txt w.r.t 中做啥?构建类型?
】我应该在CMakeLists.txtw.r.t中做啥?构建类型?【英文标题】:WhatshouldIdoinCMakeLists.txtw.r.t.thebuildtype?我应该在CMakeLists.txtw.r.t中做什么?构建类型?【发布时间】:2020-04-1912:03:54【问题描述】:我是一些使用CMake构建的库的作者。... 查看详情
/s ^ $ 在正则表达式中做啥? [关闭]
】/s^$在正则表达式中做啥?[关闭]【英文标题】:whatdo/s^$doinRegex?[closed]/s^$在正则表达式中做什么?[关闭]【发布时间】:2013-12-2402:01:32【问题描述】:所以我今天刚刚学习了正则表达式,我们没有接触到这些符号/s^$我问的原因... 查看详情
如果发生内部提交,我可以在 Oracle 中做啥以保留保存点?
】如果发生内部提交,我可以在Oracle中做啥以保留保存点?【英文标题】:WhatcanidoinOracleinordertopreservethesavepointifinternalcommitoccurs?如果发生内部提交,我可以在Oracle中做什么以保留保存点?【发布时间】:2012-11-0615:17:43【问题描... 查看详情
watchOS 3 - 我应该在 userNotificationCenter:willPresentNotification:withCompletionHandler: 中做啥来实际显示通知?
】watchOS3-我应该在userNotificationCenter:willPresentNotification:withCompletionHandler:中做啥来实际显示通知?【英文标题】:watchOS3-WhatamIsupposedtodoinuserNotificationCenter:willPresentNotification:withCompletionHandler:toactuallyshowthenot 查看详情
celery.utils.log.ProcessAwareLoggerobject 在 logging.Logger.manager.loggerDict 中做啥
】celery.utils.log.ProcessAwareLoggerobject在logging.Logger.manager.loggerDict中做啥【英文标题】:Whatiscelery.utils.log.ProcessAwareLoggerobjectdoinginlogging.Logger.manager.loggerDictcelery.utils.log.ProcessAwareLoggerobject在loggi 查看详情