687

Kotlin 中这个表达式的等价物是什么?

a ? b : c

这不是 Kotlin 中的有效代码。

4

34 回答 34

880

在 Kotlin 中,if语句是表达式。所以下面的代码是等价的:

if (a) b else c

表达式和语句之间的区别在这里很重要。在 Java/C#/JavaScript 中,if形成一个语句,这意味着它不会解析为一个值。更具体地说,您不能将其分配给变量。

// Valid Kotlin, but invalid Java/C#/JavaScript
var v = if (a) b else c

如果你的语言if是陈述,这可能看起来不自然,但这种感觉应该很快就会消退。

于 2013-05-02T11:08:15.273 回答
133

TL;博士

if (a) b else c

^ 是您可以使用的,而不是a ? b : cKotlin 语法不允许的三元运算符表达式。


在 Kotlin 中,许多控制语句,例如if, when,甚至try,都可以用作表达式。因此,这些语句可以有一个结果,可以分配给一个变量,从一个函数返回,等等。

从语法上讲,不需要三元运算符

由于 Kotlin 的表达式,该语言实际上并不需要三元运算符

if (a) b else c

是您可以使用的,而不是三元运算符表达式a ? b : c

我认为这个想法是前一个表达式更具可读性,因为每个人都知道做什么ifelse,而? :如果您不熟悉语法,则相当不清楚。

尽管如此,我不得不承认,我经常会错过更方便的三元运算符。


其他选择

什么时候

检查条件时,您可能还会看到whenKotlin 中使用的构造。这也是一种以另一种方式表达 if-else 级联的方式。以下对应于 OT 示例。

when(a) {
    true -> b
    false -> c
}

扩展

正如其他答案中的许多很好的示例(Kotlin 三元条件运算符)所示,扩展也可以帮助解决您的用例。

于 2017-10-20T06:20:17.017 回答
93

您可以定义自己的Boolean扩展函数,该函数在提供类似于三元运算符的结构null时返回:Booleanfalse

infix fun <T> Boolean.then(param: T): T? = if (this) param else null

这将使a ? b : c表达式转换为a then b ?: c,如下所示:

println(condition then "yes" ?: "no")

更新: 但是要进行更多类似 Java 的条件切换,您将需要类似的东西

infix fun <T> Boolean.then(param: () -> T): T? = if (this) param() else null

println(condition then { "yes" } ?: "no") 注意 lambda。condition它的内容计算应该推迟到我们确定true

这个看起来很笨拙,这就是为什么存在将 Java 三元运算符移植到 Kotlin 的高要求请求

于 2016-09-25T13:07:52.920 回答
52

Java 等效的三元运算符

a ? b : c

在一行中是 Kotlin 中的一个简单 IF

if(a) b else c

没有三元运算符(条件?那么:否则),因为普通的 if 在这个角色中可以正常工作。

https://kotlinlang.org/docs/reference/control-flow.html#if-expression


Null 比较的特殊情况

你可以使用猫王运算符

if ( a != null ) a else b
// equivalent to
a ?: b
于 2019-06-01T07:00:51.067 回答
40

对于我自己,我使用以下扩展功能:

fun T?.or<T>(default: T): T = if (this == null) default else this 
fun T?.or<T>(compute: () -> T): T = if (this == null) compute() else this

如果对象等于 null,第一个将返回提供的默认值。第二个将在相同的情况下评估 lambda 中提供的表达式。

用法:

1) e?.getMessage().or("unknown")
2) obj?.lastMessage?.timestamp.or { Date() }

就我个人而言,上面的代码比if构造内联更具可读性

于 2015-07-08T15:41:39.773 回答
35

其他答案中未提及的一些极端情况。

由于takeIfKotlin 1.1中出现,三元运算符a ? b : c也可以这样表示:

b.takeIf { a } ?: c

如果 c 是 ,这将变得更短null

b.takeIf { a }

另请注意,Java 世界中典型的空检查,例如value != null ? value : defaultValue在 ideomatic Kotlin 中将 translate 转换为 just value ?: defaultValue

类似a != null ? b : c的可以翻译成a?.let { b } ?: c

于 2017-06-11T12:30:06.980 回答
33

kotlin中没有三元运算符if else,因为块返回值

所以,你可以这样做: val max = if (a > b) a else b 而不是java的max = (a > b) ? b : c

我们也可以使用when构造,它也返回值:

val max = when(a > b) {
    true -> a
    false -> b
}

这是 kotlin 文档的链接:控制流:如果、何时、对于、而

于 2017-07-26T08:05:50.670 回答
31

在 Kotlin 中,if是一个表达式,即它返回一个值。因此没有三元运算符(condition ? then : else),因为普通的 if 在这个角色中可以正常工作。 来自这里的手动来源

// Traditional usage 
var max = a 
if (a < b) max = b

// With else 
var max: Int
if (a > b) {
    max = a
} else {
    max = b
}

// As expression 
val max = if (a > b) a else b
于 2017-05-24T05:30:11.613 回答
30

任务

让我们考虑以下示例:

if (!answer.isSuccessful()) {
    result = "wrong"
} else {
    result = answer.body().string()
}
return result

我们在 Kotlin 中需要以下等价物:

返回 ( !answer.isSuccessful() ) ? “错误” : answer.body().string()


解决方案1.a。您可以if-expression在 Kotlin 中使用:

return if (!answer.isSuccessful()) "wrong" else answer.body().string()

解决方案1.b。如果你翻转它会更好if-expression(让我们不这样做not):

return if (answer.isSuccessful()) answer.body().string() else "wrong"


解决方案 2。Kotlin 的 Elvis 运算符?:可以做得更好:

return answer.body()?.string() ?: "wrong"


解决方案 3。或者使用Extension function对应的Answer类:

fun Answer.bodyOrNull(): Body? = if (isSuccessful()) body() else null


解决方案 4。使用Extension function可以减少代码,这要归功于Elvis operator

return answer.bodyOrNull()?.string() ?: "wrong"


解决方案 5。或者只使用when运算符:

when (!answer.isSuccessful()) {
    parseInt(str) -> result = "wrong"
    else -> result = answer.body().string()
}
于 2019-01-09T16:26:34.263 回答
27

看看文档

在 Kotlin 中,if 是一个表达式,即它返回一个值。因此没有三元运算符(条件?那么:else),因为普通的 if 在这个角色中可以正常工作。

于 2016-07-28T06:21:47.710 回答
17

爪哇

int temp = a ? b : c;

相当于 Kotlin:</p>

var temp = if (a) b else c
于 2017-06-27T15:14:03.717 回答
17

另一种有趣的方法是使用when

when(a) {
  true -> b
  false -> c
}

在一些更复杂的场景中可以非常方便。老实说,它对我来说比if ... else ...

于 2017-07-26T06:59:40.847 回答
15

Kotlin 中没有三元运算符。乍一看似乎有问题。但是认为我们可以使用内联 if else 语句来做到这一点,因为这是这里的表达式。简单地说,我们必须做 -

var number = if(n>0) "Positive" else "Negetive"

在这里,我们可以根据需要阻止太多。喜欢-

var number = if(n>0) "Positive" else if(n<0) "Negative" else "Zero"

所以这一行比三元运算符简单易读。当我们在 java 中使用多个三元运算符时,这看起来很可怕。但是这里我们有一个清晰的语法。甚至我们也可以将它写成多行。

于 2017-06-09T22:40:26.743 回答
15

Kotlin 没有三元运算符。您可以使用if如下所示的正则表达式:

if (condition) exp1 else exp2

此外,除了if在 Kotlin 中不是语句而是表达式(即它计算为一个值)这一事实之外,如果您在if分支的主体(或 or 的主体else)中有多个语句else if,最后一行块的值是该分支的值。例如:

if (a>b) {
    println("a is greater than b")
    a // value of this if
} else {
    println("b is greater than a")
    b // value of else
}
于 2020-09-12T07:53:08.207 回答
14

when 替换了类 C 语言的 switch 运算符。在最简单的形式中,它看起来像这样

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> {
        print("x is neither 1 nor 2")
    }
}
于 2017-05-23T10:21:38.823 回答
13

您可以使用var a= if (a) b else c代替三元运算符。

kotlin 的另一个好概念是 Elvis operator。您不需要每次都检查 null 。

val l = b?.length ?: -1

如果 b 不为空,这将返回长度,否则将执行右侧语句。

于 2018-10-25T06:58:29.263 回答
12

正如 Drew Noakes 所引用的,kotlin 使用 if 语句作为表达式,因此不再需要三元条件运算符,

但是通过扩展函数和中缀重载,你可以自己实现,这里是一个例子

infix fun <T> Boolean.then(value: T?) = TernaryExpression(this, value)

class TernaryExpression<out T>(val flag: Boolean, val truly: T?) {
    infix fun <T> or(falsy: T?) = if (flag) truly else falsy
}

然后像这样使用它

val grade = 90
val clazz = (grade > 80) then "A" or "B"
于 2017-06-07T09:20:32.857 回答
9

您可以在 Kotlin 中以多种方式做到这一点

  1. 使用如果

    if(a) b else c
    
  2. 何时使用

    when (a) { 
        true -> print("value b") 
        false -> print("value c") 
        else -> {  
            print("default return in any other case") 
        } 
    }
    
  3. 零安全

    val a = b ?: c
    
于 2017-10-02T18:33:23.043 回答
9

Kotlin 中没有三元运算,但有一些有趣的方法可以解决这个问题。正如其他人所指出的,直接翻译成 Kotlin 应该是这样的:

val x = if (condition) result1 else result2

但是,就个人而言,我认为这可能会有点混乱且难以阅读。库中还内置了一些其他选项。您可以将 takeIf {} 与 elvis 运算符一起使用:

val x = result1.takeIf { condition } ?: result2

那里发生的情况是 takeIf { } 命令返回您的 result1 或 null,并且 elvis 运算符处理 null 选项。还有一些附加选项,takeUnless { },例如:

val x = result1.takeUnless { condition } ?: result2

语言很清楚,你知道那在做什么。

如果这是一个常用的条件,你也可以做一些有趣的事情,比如使用内联扩展方法。例如,假设我们想要以 Int 形式跟踪游戏得分,并且如果不满足给定条件,我们希望始终返回 0:

inline fun Int.zeroIfFalse(func: () -> Boolean) : Int = if (!func.invoke()) 0 else this     

好吧,这看起来很难看。但是考虑一下它在使用时的样子:

var score = 0
val twoPointer = 2
val threePointer = 3

score += twoPointer.zeroIfFalse { scoreCondition } 
score += threePointer.zeroIfFalse { scoreCondition } 

如您所见,Kotlin 在您选择如何表达代码方面提供了很大的灵活性。我的例子有无数种变体,可能我什至还没有发现。我希望这有帮助!

于 2018-02-04T21:06:04.927 回答
8

你可以这样做:

val ans = (exp1 == exp2) then "yes" ?: "no"

通过使用这个扩展:

infix fun<T> Boolean.then(first: T): T? = if (this) first else null

PS:不要把上面的中缀函数修改成accept first: T?,表达式会逻辑不正确。例如:如果您将其修改为接受 nullable first: T?,那么val ans = (true == true) then null ?: "abcd",ans将是"abcd",这是不正确的。

于 2021-02-27T10:37:17.873 回答
7

如果您不使用标准符号,您也可以使用中创建/模拟它,如下所示:

创建一个类来保存您的目标和结果:

data class Ternary<T>(val target: T, val result: Boolean)

创建一些中缀函数来模拟三元运算

infix fun <T> Boolean.then(target: T): Ternary<T> {
    return Ternary(target, this)
}

infix fun <T> Ternary<T>.or(target: T): T {
    return if (this.result) this.target else target
}

然后你就可以像这样使用它了:

val collection: List<Int> = mutableListOf(1, 2, 3, 4)

var exampleOne = collection.isEmpty() then "yes" or "no"
var exampleTwo = (collection.isNotEmpty() && collection.contains(2)) then "yes" or "no"
var exampleThree = collection.contains(1) then "yes" or "no"
于 2019-06-27T19:30:49.830 回答
6

请记住,与许多流行语言不同,三元运算符Elvis 运算符在Kotlin中具有不同的含义。这样做会给Kotlin编译器expression? value1: value2带来坏话,这与任何其他语言不同,因为 Kotlin 中没有官方文档中提到的三元运算符。原因是if、when 和 try-catch语句本身返回值。

因此,doingexpression? value1: value2可以替换为

val max = if (a > b) print("选择 a") else print("选择 b")

Kotlin拥有的Elvis 运算符仅适用于可为空变量的情况,例如:

如果我做了类似的事情,value3 = value1 ?: value2那么如果value1,那么value2将被返回,否则value1将被返回。

从这些答案中可以得到更清晰的理解。

于 2019-03-04T18:00:15.913 回答
4

您可以if在 Kotlin 中为此使用表达式。在 Kotlinif中是一个带有结果值的表达式。所以在 Kotlin 中我们可以写

fun max(a: Int, b: Int) = if (a > b) a else b

在 Java 中,我们可以实现相同但使用更大的代码

int max(int a, int b) {
return a > b ? a : b
}
于 2018-01-06T09:41:22.523 回答
2

为什么要使用这样的东西:

when(a) {
  true -> b
  false -> b
}

当您实际上可以使用这样的东西时(a在这种情况下是布尔值):

when {
  a -> b
  else -> b
}
于 2018-07-24T11:40:49.073 回答
2

另一种简短的使用方法

val value : String = "Kotlin"

value ?: ""

这里 kotlin 本身检查 null 值,如果它为 null 则传递空字符串值。

于 2017-09-22T09:32:12.497 回答
2

当使用 apply() 时, let 在处理三元运算时看起来非常方便,因为它更优雅并且给你空间

val columns: List<String> = ...
val band = Band().apply {
    name = columns[0]
    album = columns[1]
    year = columns[2].takeIf { it.isNotEmpty() }?.let { it.toInt() } ?: 0
}
于 2018-01-28T23:51:07.743 回答
2

在 Kotlin 中,您可以像这样使用三元运算:val x = if(a) "add b" else "add c"

于 2020-05-26T08:23:45.220 回答
1

此处的其他答案例如takeIf假设类似于x = (a != null) ? a : corx = (a != null) ? a.method() : c但这实际上并不等同于x = a ? b : c

要使用空安全检查(即)实现真正等效的三元运算符,x = (a != null) ? b : c您可以使用let代替takeIf,即

val x = a?.let {b} ?: c

其中 b 可能是也可能不是在 a 上调​​用某些东西的方法。

于 2021-08-17T11:36:21.813 回答
1

使用以下中缀函数,我可以涵盖许多常见的用例,几乎可以在 Python 中完成:

class TestKotlinTernaryConditionalOperator {

    @Test
    fun testAndOrInfixFunctions() {
        Assertions.assertThat(true and "yes" or "no").isEqualTo("yes")
        Assertions.assertThat(false and "yes" or "no").isEqualTo("no")

        Assertions.assertThat("A" and "yes" or "no").isEqualTo("yes")
        Assertions.assertThat("" and "yes" or "no").isEqualTo("no")

        Assertions.assertThat(1 and "yes" or "no").isEqualTo("yes")
        Assertions.assertThat(0 and "yes" or "no").isEqualTo("no")

        Assertions.assertThat(Date() and "yes" or "no").isEqualTo("yes")
        @Suppress("CAST_NEVER_SUCCEEDS")
        Assertions.assertThat(null as Date? and "yes" or "no").isEqualTo("no")
    }
}

infix fun <E> Boolean?.and(other: E?): E? = if (this == true) other else null
infix fun <E> CharSequence?.and(other: E?): E? = if (!(this ?: "").isEmpty()) other else null
infix fun <E> Number?.and(other: E?): E? = if (this?.toInt() ?: 0 != 0) other else null
infix fun <E> Any?.and(other: E?): E? = if (this != null) other else null
infix fun <E> E?.or(other: E?): E? = this ?: other
于 2017-11-17T15:55:24.843 回答
1

在 Java 中,if 是一个语句,但在 Kotlin 中,if 是一个表达式。之所以称为表达式,是因为它比较 a 和 b 的值并返回最大值。因此,在 Kotlin 中没有三元运算符 (a>b)?a:b 因为它被 if 表达式所取代。

于 2021-07-19T09:07:52.537 回答
1

Kotlin 中没有三元运算符,最封闭的是以下两种情况,

  • if else 作为表达式语句

val a = true if(a) print("A is true") else print("A is false")

  • 猫王算子

如果 ?: 左边的表达式不为 null,则 elvis 运算符返回它,否则返回右边的表达式。请注意,仅当左侧为空时才计算右侧表达式。

 val name = node.getName() ?: throw IllegalArgumentException("name expected")

参考文档

于 2018-07-02T10:58:51.790 回答
0

有趣的 max(x:Int,y:Int) : String = if (x>y) "max = $x" else "max = $y"

内联函数

于 2020-08-02T14:48:29.967 回答
0

例如: var energy: Int = data?.get(position)?.energy?.toInt() ?: 0

在 kotlin 中,如果您使用 ?: 它将像语句将返回 null 然后 ?: 0一样工作,它将采用 0 或您在这方面编写的任何内容。

于 2018-07-19T06:38:58.753 回答
0

如果有人需要隐式转换的三元运算符:

/**'[_t]' for ternary operator*/
@Suppress("FunctionName")
@OptIn(ExperimentalContracts::class)
fun <T> _t(bool: Boolean, onTrue: T, onFalse: T): T
{
    contract { returns() implies bool }
    return if (bool) onTrue else onFalse
}

虽然不确定这有多大用处

于 2020-07-30T16:02:26.640 回答