问题
What is the equivalent of this expression in Kotlin?
a ? b : c
This is not valid code in Kotlin.
回答1:
In Kotlin, if
statements are expressions. So the following code is equivalent:
if (a) b else c
The distinction between expression and statement is important here. In Java/C#/JavaScript, if
forms a statement, meaning that it does not resolve to a value. More concretely, you can't assign it to a variable.
// Valid Kotlin, but invalid Java/C#/JavaScript
var v = if (a) b else c
If you're coming from a language where if
is a statement, this might seem unnatural but that feeling should soon subside.
回答2:
You could define your own Boolean
extension function that returns null
when the Boolean
is false
to provide a structure similar to the ternary operator:
infix fun <T> Boolean.then(param: T): T? = if (this) param else null
This would make an a ? b : c
expression translate to a then b ?: c
, like so:
println(condition then "yes" ?: "no")
Update: But to do some more Java-like conditional switch you will need something like that
infix fun <T> Boolean.then(param: () -> T): T? = if (this) param() else null
println(condition then { "yes" } ?: "no")
pay attention on the lambda. its content calculation should be postponed until we make sure condition
is true
This one looks clumsy, that is why there is high demanded request exist to port Java ternary operator into Kotlin
回答3:
TL;DR
if (a) b else c
is what you can use instead of the Java expression a ? b : c
.
In Kotlin, many control statements including if
, when
or even try
can be used as expressions. This means that those can have a result which can be assigned to a variable, returned from a function etc.
Syntactically, no need for ternary operator
As a result, Kotlin does not need the ternary operator.
if (a) b else c
is what you can use instead of the Java expression a ? b : c
.
I think the idea is that the latter is less readable since everybody knows what ifelse
does, whereas ? :
is rather inconvenient if you're not familar with the syntax already. Although I have to admit that I often miss the more convenient ternary operator.
Other Alternatives
when
You might also see a lot when
constructs whenever conditions are checked in Kotlin. It's also a way to express if-else cascades in an alternative way. The following corresponds to your example.
when(a) {
true -> b
false -> c
}
Extensions
As many good examples (Kotlin Ternary Conditional Operator) in the other answers show, extensions can also be a way to go.
回答4:
For myself I use following extension functions:
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
First one will return provided default value in case object equals null. Second will evaluate expression provided in lambda in the same case.
Usage:
1) e?.getMessage().or("unknown")
2) obj?.lastMessage?.timestamp.or { Date() }
Personally for me code above more readable than if
construction inlining
回答5:
There is no ternary operator in kotlin, as the if else
block returns value
so, you can do:
val max = if (a > b) a else b
instead of java's max = (a > b) ? b : c
We can also use when
construction, it also return value:
val max = when(a > b) {
true -> a
false -> b
}
Here is link for kotlin documentation : Control Flow: if, when, for, while
回答6:
In Kotlin,
if
is an expression, i.e. it returns a value. Therefore there is no ternary operator(condition ? then : else)
, because ordinary if works fine in this role. manual source from here
// 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
回答7:
Some corner cases not mentioned in other answers.
Since appearance of takeIf in Kotlin 1.1 the ternary operator a ? b : c
can also be expressed like this:
b.takeIf { a } ?: c
This becomes even shorter in case c is null
:
b.takeIf { a }
Also note that typical in Java world null checks like value != null ? value : defaultValue
translate in ideomatic Kotlin to just value ?: defaultValue
.
Similar a != null ? b : c
can be translated to a?.let { b } ?: c
.
回答8:
Take a look at the docs:
In Kotlin, if is an expression, i.e. it returns a value. Therefore there is no ternary operator (condition ? then : else), because ordinary if works fine in this role.
回答9:
Java's equivalent of ternary operator
a ? b : c
is a simple IF in Kotlin in one line
if(a) b else c
there is no ternary operator (condition ? then : else), because ordinary if works fine in this role.
https://kotlinlang.org/docs/reference/control-flow.html#if-expression
Special case for Null comparison
you can use the Elvis operator
if ( a != null ) a else b
// equivalent to
a ?: b
回答10:
Java
int temp = a ? b : c;
Equivalent to Kotlin:
var temp = if (a) b else c
回答11:
when replaces the switch operator of C-like languages. In the simplest form it looks like this
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("x is neither 1 nor 2")
}
}
回答12:
There is no ternary operator in Kotlin. It seems problematic at the first glance. But think we can do it with inline if else statement because this is expression here. Simply we have to do -
var number = if(n>0) "Positive" else "Negetive"
Here we can else if block too as many as we need. Like-
var number = if(n>0) "Positive" else if(n<0) "Negative" else "Zero"
So this line is so simple and much readable than ternary operator. when we use more than one ternary operator in java it seems horrible. But here we have a clear syntax. even we can write it in multiple line too.
回答13:
You can use var a= if (a) b else c
in place of the ternary operator.
Another good concept of kotlin is Elvis operater. You don't need to check null every time.
val l = b?.length ?: -1
This will return length if b is not null otherwise it executes right side statement.
回答14:
as Drew Noakes quoted, kotlin use if statement as expression, so Ternary Conditional Operator is not necessary anymore,
but with the extension function and infix overloading, you could implement that yourself, here is an example
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
}
then use it like this
val grade = 90
val clazz = (grade > 80) then "A" or "B"
回答15:
You can do it many way in Kotlin
Using if
if(a) b else c
Using when
when (a) { true -> print("value b") false -> print("value c") else -> { print("default return in any other case") } }
Null Safety
val a = b ?: c
回答16:
TASK:
Let's consider the following example:
if (!answer.isSuccessful()) {
result = "wrong"
} else {
result = answer.body().string()
}
return result
We need the following equivalent in Kotlin:
return (!answer.isSuccessful())
?
"wrong":
answer.body().string()
SOLUTIONS:
1.a. You can use if-expression
in Kotlin:
return if (!answer.isSuccessful()) "wrong" else answer.body().string()
1.b. It can be much better if you flip this if-expression
(let's do it without not
):
return if (answer.isSuccessful()) answer.body().string() else "wrong"
2. Kotlin’s Elvis operator ?:
can do a job even better:
return answer.body()?.string() ?: "wrong"
3. Or use an Extension function
for the corresponding Answer
class:
fun Answer.bodyOrNull(): Body? = if (isSuccessful()) body() else null
4. Using the Extension function
you can reduce a code thanks to Elvis operator
:
return answer.bodyOrNull()?.string() ?: "wrong"
5. Or just use when
operator:
when (!answer.isSuccessful()) {
parseInt(str) -> result = "wrong"
else -> result = answer.body().string()
}
Hope this helps.
回答17:
Another interesting approach would be to use when
:
when(a) {
true -> b
false -> b
}
Can be quite handy in some more complex scenarios. And honestly, it's more readable for me than if ... else ...
回答18:
There is no ternary operation in Kotlin, but there are some fun ways to work around that. As others have pointed out, a direct translation into Kotlin would look like this:
val x = if (condition) result1 else result2
But, personally, I think that can get a bit cluttered and hard to read. There are some other options built into the library. You can use takeIf {} with an elvis operator:
val x = result1.takeIf { condition } ?: result2
What is happening there is that the takeIf { } command returns either your result1 or null, and the elvis operator handles the null option. There are some additional options, takeUnless { }, for example:
val x = result1.takeUnless { condition } ?: result2
The language is clear, you know what that's doing.
If it's a commonly used condition, you could also do something fun like use an inline extension method. Let's assume we want to track a game score as an Int, for example, and we want to always return 0 if a given condition is not met:
inline fun Int.zeroIfFalse(func: () -> Boolean) : Int = if (!func.invoke()) 0 else this
Ok, that seems ugly. But consider how it looks when it is used:
var score = 0
val twoPointer = 2
val threePointer = 3
score += twoPointer.zeroIfFalse { scoreCondition }
score += threePointer.zeroIfFalse { scoreCondition }
As you can see, Kotlin offers a lot of flexibility in how you choose to express your code. There are countless variations of my examples and probably ways I haven't even discovered yet. I hope this helps!
回答19:
Remember Ternary operator and Elvis operator hold separate meanings in Kotlin unlike in many popular languages. Doing expression? value1: value2
would give you bad words by the Kotlin compiler, unlike any other language as there is no ternary operator in Kotlin as mentioned in the official docs. The reason is that the if, when and try-catch statements themselves return values.
So, doing expression? value1: value2
can be replaced by
val max = if (a > b) print("Choose a") else print("Choose b")
The Elvis operator that Kotlin has, works only in the case of nullable variables ex.:
If I do something like
value3 = value1 ?: value2
then if value1 is null then value2 would be returned otherwise value1 would be returned.
A more clear understanding can be achieved from these answers.
回答20:
You can use if
expression for this in Kotlin. In Kotlin if
is an expression with a result value. So in Kotlin we can write
fun max(a: Int, b: Int) = if (a > b) a else b
and in Java we can achieve the same but with larger code
int max(int a, int b) {
return a > b ? a : b
}
回答21:
Another short approach to use
val value : String = "Kotlin"
value ?: ""
Here kotlin itself checks null value and if it is null then it passes empty string value.
回答22:
Why would one use something like this:
when(a) {
true -> b
false -> b
}
when you can actually use something like this (a
is boolean in this case):
when {
a -> b
else -> b
}
回答23:
With the following infix functions I can cover many common use cases pretty much the same way it can be done in 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
回答24:
There is no ternary operator in Kotlin, the most closed are the below two cases,
- If else as expression statement
val a = true if(a) print("A is true") else print("A is false")
- Elvis operator
If the expression to the left of ?: is not null, the elvis operator returns it, otherwise it returns the expression to the right. Note that the right-hand side expression is evaluated only if the left-hand side is null.
val name = node.getName() ?: throw IllegalArgumentException("name expected")
Reference docs
回答25:
example: var energy: Int = data?.get(position)?.energy?.toInt() ?: 0
In kotlin if you are using ?: it will work like if the statement will return null then ?: 0 it will take 0 or whatever you have write this side.
回答26:
When working with apply(), let seems very handy when dealing with ternary operations, as it is more elegant and give you room
val columns: List<String> = ...
val band = Band().apply {
name = columns[0]
album = columns[1]
year = columns[2].takeIf { it.isNotEmpty() }?.let { it.toInt() } ?: 0
}
回答27:
If you do not what to use the standard notation you can also create/simulate it using infix with something like this:
create a class to hold your target and result:
data class Ternary<T>(val target: T, val result: Boolean)
create some infix functions to simulate a ternary operation
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
}
Then you will be able to use it like this:
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"
回答28:
After some research of other ideas, I've derived the following ternary operator:
infix fun <T : Any> Boolean.yes(trueValue: T): T? = if (this) trueValue else null
infix fun <T : Any> T?.no(falseValue: T): T = this ?: falseValue
Example (run here):
fun main() {
run {
val cond = true
val result = cond yes "True!" no "False!"
println("ternary test($cond): $result")
}
run {
val cond = false
val result = cond yes "True!" no "False!"
println("ternary test($cond): $result")
}
}
This version is fluent and does not conflict with the null coalescing operator.
来源:https://stackoverflow.com/questions/16336500/kotlin-ternary-conditional-operator