Operators can be used to perform basic computations in expressions. Most operators take two expressions as arguments (also called operands), make a computation based on the expressions, and return the result.
Operators are invoked in expressions using the following syntax, where expr1 and expr2 are expressions, and operator is the operator to invoke.
expr1 operator expr2Operator invocations can be composed into bigger expressions, where different operators have different precedence levels. This means that in a chain of operator invocations (e.g., expr1 operator1 expr2 operator2 expr3), the order of operator invocation is not necessarily the syntactical order.
For example, the multiplication operator * has a higher precedence than the addition operator +, so the expression 1+2*3 will actually be executed as first computing 2*3=6, and then adding the result to 1—rather than the syntactical order which would be computing 1+2 and then multiplying by 3. Parenthesis can be used to override precedence rules. For example, the expression (1+2)*3 will be computed by first computing 1+2 and then multiplying the result by 3.
These operators are supported in expressions (shown here in descending order of precedence):
| Precedence | Operator | Description |
|---|---|---|
| 11 | - | Unary minus |
| 11 | ! | Unary negation |
| 11 | ~ | Unary bitwise negation |
| 10 | / | Divide; 10 / 2 = 5 |
| 10 | * | Multiply; 3 * 2 = 6 or "a" * 3 = "aaa" |
| 10 | % | Modulo; 10 % 3 = 1 |
| 9 | + | Add; 10 + 2 = 12; "hello" + "world" = "hello world" |
| 9 | - | Subtract; 10 - 2 = 8 (shift ones) |
| 8 | << | Bitwise 'shift left' |
| 8 | >> | Bitwise 'shift right' |
| 7 | >= | Greater than or Equal; 10>=2 = true, 2>=10 = false, 10<=10 = true |
| 7 | <= | Less than or Equal; 10<=2 = false, 2<=10 = true, 10<=10 = true |
| 7 | > | Greater than; 10>2 = true, 2>10 = false |
| 7 | < | Less than; 10<2 = false, 2<10 = true |
| 6 | == | Equals; 10==10 = true; 9==10 = false; "hello"=="hello" = true |
| 6 | != | Not equals; 3!=2 = true; "hello"!="hello" = false |
| 5 | & | Bitwise 'and' |
| 4 | ^ | Bitwise 'xor' |
| 3 | | | Bitwise 'or' |
| 2 | && | Logical and; see notes. |
| 1 | || | Logical or; see notes |
The operators && and || have the special property that they control evaluation flow. For all other operators, both operands of the operator are always evaluated. However for these two operators, this is not the case. Their computation is executed as follows:
The
&&operator first evaluates the left operand. If its truth-value is false, then false returned; the right operand will not be evaluated in this case. If the truth-value of the left operand is true, then the right operand is evaluated and its value is returned.The
||operator first evaluates the left operand. If its truth-value is true, then the left operand's value is returned; the right operand will not be evaluated in this case. If the truth-value of the left operand is false, then the right operand is evaluated and its value is returned.
Using the short-circuiting Boolean operators, expressions can be written to guard against error cases.
For example, the expression (maybeObject && maybeObject.maybeField) || defaultValue will return the value of field maybeField of object maybeObject if maybeObject is a non-null value. Otherwise, defaultValue will be returned. Notice that if maybeObject is a null object, maybeObject.maybeField doesn't even get evaluated (if it would have, then the evaluation would have terminated with an error).
An expression of the form:
cond ? trueExpr : falseExprwhere cond, trueExpr and falseExpr are all expressions, is evaluated as follows. First the cond expression is evaluated. Depending on its result's truth-value, either the trueExpr or falseExpr expression is evaluated and the resulting value is returned. Note that only one of these expressions is evaluated so even if the other one would have returned an error if it were evaluated—this does not impact the expression result.