The difference between &&
and and
and the difference between ||
and or
:
&&
and||
use short-circuit evaluation whileand
andor
always evaluate every condition
But apart from that, I get different behaviour for the following example:
Using &&
, this snippet perfectly works:
var str1: String? = "Good Morning"
var str2: String? = "How's it going"
if (str1 != null && str2 != null) {
println(str1.length str2.length)
}
When I replace the &&
with and
I have to add parenthesis around both conditions, otherwise the compiler seems to get confused because I get the error: Operator '!=' cannot be applied to 'String?' and 'BigInteger'
Using and
and adding parenthesis:
var str1: String? = "Good Morning"
var str2: String? = "How's it going"
if ((str1 != null) and (str2 != null)) {
println(str1.length str2.length)
}
But this last snippet throws:
Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
Shouldn't both expressions do precisely the same? Evaluate both conditions and only execute the println
when both String
values are non-null
? What is the difference?
CodePudding user response:
&&
is different from and
in an additional way in that it introduces a smart cast from String?
to String
, allowing you to access length
by saying str1.length
and str2.length
, rather than using str1?.length
and str2?.length
.
From the Kotlin language specification:
Smart casts are introduced by the following Kotlin constructions.
- Conditional expressions (
if
)- When expressions (
when
);- Elvis operator (operator
?:
);- Safe navigation operator (operator
?.
);- Logical conjunction expressions (operator
&&
);- Logical disjunction expressions (operator
||
);- Not-null assertion expressions (operator
!!
);- Cast expressions (operator
as
);- Type-checking expressions (operator
is
);- Simple assignments;
- Platform-specific cases: different platforms may add other kinds of expressions which introduce additional smart cast sources.
You need the extra parenthesis because and
, being an infix function, has a higher precedence than &&
, which is not an infix function. See all the precedences here.