Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Java  Module 2 – Variables, types and operators

Operators, precedence and short-circuiting

Java's operator precedence and associativity, left-to-right evaluation, why i = i++ leaves i unchanged, short-circuit && and ||, and the type of ?:.

  • Beginner
  • 15 minutes
  • Examples run with Java 25.0.4 and Python 3.14.8
  • By MySmartCoPilot
Free: 15 minutes

What you will learn

  • Evaluate expressions using Java's precedence and associativity rules
  • Predict the order in which Java evaluates operands, and avoid side effects such as k = k++
  • Prevent errors with && and || short-circuiting
  • Determine the type of a conditional expression from its two branches
  • Write string concatenation that adds numbers first where it must

Before you start

What you’ll learn · Before you start

What you will learn

  • Evaluate expressions using Java's precedence and associativity rules
  • Predict the order in which Java evaluates operands, and avoid side effects such as k = k++
  • Prevent errors with && and || short-circuiting
  • Determine the type of a conditional expression from its two branches
  • Write string concatenation that adds numbers first where it must

Before you start

On this page

When an expression has several operators, operator precedence: The rule that decides how an expression with several operators is grouped: * binds tighter than +, so 1 + 2 * 3 is 1 + (2 * 3). Parentheses override it, and it never changes the left-to-right order of evaluation. decides how Java groups it: * binds tighter than +, so 1 + 2 * 3 is 1 + (2 * 3), which is 7. associativity: The rule that groups a chain of operators of the same precedence: most binary operators group from the left, so 10 - 4 - 3 is (10 - 4) - 3, while assignment and ?: group from the right, so a = b = 8 assigns b first. settles ties between operators of the same level: most binary operators group from left to right, so 10 - 4 - 3 is 3, while assignment and ?: group from right to left. Grouping is not the same as order: Java always evaluates the operands from left to right, so in a() + b() * c() the method a runs first although the multiplication is grouped first.

&& and || can skip work: they short-circuit evaluation: How && and || work: the right operand is evaluated only when the left one has not decided the result, so s != null && s.isEmpty() never calls a method on null. & and | always evaluate both sides., evaluating their right operand only when the left one has not already decided the answer, which is what makes s != null && s.isEmpty() safe. You will run twelve expressions through the precedence rules on JDK 25, step through the order in which k = k++ runs, and meet the traps of ++, of string + and of the conditional operator’s type.

Precedence decides how an expression is grouped

The table lists Java’s operators from the tightest binding to the loosest. Operators on one row have the same precedence, and the last column says how a chain of them groups:

Operators What they are A chain groups
x++ x-- postfix increment and decrement
++x --x +x -x ~ ! (type) prefix and unary operators, casts right to left
* / % multiplication, division, remainder left to right
+ - addition and subtraction, and string + left to right
<< >> >>> shifts left to right
< > <= >= instanceof comparisons and type tests
== != equality left to right
& bitwise AND, logical AND without short-circuit left to right
^ bitwise and logical exclusive OR left to right
| bitwise OR, logical OR without short-circuit left to right
&& conditional AND left to right
|| conditional OR left to right
? : conditional operator right to left
= += -= *= /= and the other compound assignments assignment right to left

Comparisons do not chain: a < b < c compares a boolean with c and does not compile. Write a < b && b < c.

Precedence.java Java
// Twelve expressions: precedence decides how each one is grouped, associativity breaks ties.
void main() {
    IO.println("1 + 2 * 3             = " + (1 + 2 * 3));
    IO.println("(1 + 2) * 3           = " + ((1 + 2) * 3));
    IO.println("10 - 4 - 3            = " + (10 - 4 - 3));
    IO.println("100 / 10 / 5          = " + (100 / 10 / 5));
    IO.println("2 * 3 % 4             = " + (2 * 3 % 4));
    IO.println("-7 / 2 * 2            = " + (-7 / 2 * 2));
    IO.println("1 << 2 + 1            = " + (1 << 2 + 1));
    IO.println("6 & 3 + 1             = " + (6 & 3 + 1));
    IO.println("5 > 3 == 2 > 1        = " + (5 > 3 == 2 > 1));
    IO.println("true || false && false = " + (true || false && false));
    IO.println("1 + 2 + \"3\"           = " + (1 + 2 + "3"));
    IO.println("\"1\" + 2 + 3           = " + ("1" + 2 + 3));
}
Twelve expressions, run with JDK 25 Python · precedence_session.py
from session import run, version

version()
run("""
java Precedence.java
""")

Output

# openjdk version "25.0.4.1" LTS
$ java Precedence.java
1 + 2 * 3             = 7
(1 + 2) * 3           = 9
10 - 4 - 3            = 3
100 / 10 / 5          = 2
2 * 3 % 4             = 2
-7 / 2 * 2            = -6
1 << 2 + 1            = 8
6 & 3 + 1             = 4
5 > 3 == 2 > 1        = true
true || false && false = true
1 + 2 + "3"           = 33
"1" + 2 + 3           = 123

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 precedence_session.py

Each line of output shows an expression and its value. 2 * 3 % 4 groups from the left, so it is 6 % 4, which is 2. -7 / 2 * 2 is (-7 / 2) * 2, and the integer division happens first, giving -6 instead of -7. 1 << 2 + 1 is 1 << 3, because + binds tighter than a shift, and 6 & 3 + 1 is 6 & 4 for the same reason: arithmetic binds tighter than the bitwise operators, which surprises people in mask code. true || false && false is true because && binds tighter than ||. When the grouping is not obvious at a glance, add parentheses; they cost nothing.

The tree below shows the grouping of a longer condition, with the operator that binds most loosely at the top, and numbers its operands in the order the next section explains:

The tree Java builds for price + qty * 2 > limit && member, with its operands numbered 1 to 5 in the order they are evaluated.How Java reads price + qty * 2 > limit && memberprecedence gives the shape; operands are evaluated from left to right&&>member5+limit4price1*qty223Lower in the tree means it binds tighter:* before +, + before >, > before &&.The numbers give the order in whichthe operands are evaluated.member (5) is evaluated only whenthe left side of && is true.

Precedence decides how the expression is grouped; evaluation still goes from left to right

Text description of the diagram

The expression `price + qty * 2 > limit && member` drawn as a tree, with the operator that binds most loosely at the top.

  • At the top is `&&`. Its left operand is the comparison `>`, and its right operand is `member`.
  • The left operand of `>` is the addition `+`, and its right operand is `limit`.
  • The left operand of `+` is `price`, and its right operand is the multiplication `*` of `qty` and `2`.

So the expression means `((price + (qty * 2)) > limit) && member`. The operands are numbered in the order Java evaluates them, from left to right: price 1, qty 2, the literal 2 third, limit 4 and member 5. Because `&&` short-circuits, member is evaluated only when the comparison on its left is true.

Masking and adding without parentheses

flags & 3 + 1 is flags & 4, not (flags & 3) + 1, because + binds tighter than &: the run printed 4 for 6 & 3 + 1. Write (flags & 3) + 1 when you mean to mask first.

Checkpoint

Check: Precedence and associativity

  1. Question 1 of 2 What is false || true && false?

    Choose one answer.

    A hint

    Find the operator that binds tighter first.

    Show the answer: Question 1 of 2

    Answer: false

    && binds tighter than ||, just as * binds tighter than +. The expression is false || (true && false), and true && false is false, so the whole is false.

  2. Question 2 of 2 What is 5 & 1 + 2?

    Type a number.

    A hint

    Which binds tighter, + or &?

    Show the answer: Question 2 of 2

    Answer: 1

    + binds tighter than &, so this is 5 & 3. 5 is 101 in binary and 3 is 011, so the bits both have are 001, which is 1. (5 & 1) + 2 would be 3.

Operands are evaluated from left to right

Precedence decides the shape of an expression, not when each part runs. Java evaluates the left operand of a binary operator fully before the right one, and the arguments of a method from left to right:

Order.java Java
// Operands are evaluated from left to right, whatever the precedence says about grouping.
int show(String name, int value) {
    IO.println("  evaluating " + name);
    return value;
}

void main() {
    IO.println("a + b * c:");
    int r = show("a", 1) + show("b", 2) * show("c", 3);
    IO.println("  result " + r);

    int i = 1;
    int j = i++ + i++;            // 1 + 2, and i ends at 3
    IO.println("i++ + i++ = " + j + ", then i = " + i);
    int k = 5;
    k = k++;                      // k++ gives 5, then the assignment stores 5 again
    IO.println("k = k++ leaves k = " + k);

    int[] seats = {10, 20, 30};
    int index = 0;
    seats[index] = index = 2;     // the array element is chosen before index changes
    IO.println("seats = " + Arrays.toString(seats) + ", index = " + index);
}
Evaluation order, then short-circuiting Python · order_session.py
from session import run, version

version()
run("""
java Order.java
!java ShortCircuit.java
""")

Output

# openjdk version "25.0.4.1" LTS
$ java Order.java
a + b * c:
  evaluating a
  evaluating b
  evaluating c
  result 7
i++ + i++ = 3, then i = 3
k = k++ leaves k = 5
seats = [2, 20, 30], index = 2
$ java ShortCircuit.java
true false false
name == null || name.isEmpty(): true
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.isEmpty()" because "<local1>" is null
	at ShortCircuit.main(ShortCircuit.java:10)
[exit status 1]

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 order_session.py

  • show("a", 1) + show("b", 2) * show("c", 3) prints a, b and c in that order, then multiplies 2 by 3 and adds 1.
  • i++ + i++ reads i as 1 and adds 1 to it, then reads 2 and adds 1 again, so the sum is 3 and i ends at 3.
  • k = k++ leaves k unchanged. The postfix k++ yields the old value, 5, and adds 1 to k, making it 6; then the assignment stores the old value, 5, back into k.
  • seats[index] = index = 2 picks the array element first, with index still 0, and only then evaluates the right side, so seats[0] becomes 2.

The third line is the one that surprises people most. Step through it and watch the value k holds after every step:

Interactive · step by step k = k++, one step at a time Step through the assignment and watch the value k holds, on the right, after every step.
k = k++, one step at a time, step 5 of 5. Showing k = k++;, k (holds 5 again), 1. the target, 2. k++, 3. the assignment. In focus: k = k++;.writes hereadds 1stores 5k = k++;the statementkholds 5 again1. the targetk, found first2. k++yields 5, then adds 13. the assignmentstores what k++ yielded

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. The statement. k holds 5, and the statement is k = k++;. Java evaluates the left side of an assignment, its target, before anything on the right.
  2. The target first. The target is the variable k itself. Nothing is read or changed yet; Java only notes where the result will go.
  3. k++ yields the old value. The right side, k++, yields the value k has, 5, and then adds 1 to k, which now holds 6.
  4. The assignment stores 5. The assignment stores the value the right side yielded, 5, into k, over the 6. The run printed k = k++ leaves k = 5.
  5. Defined, and hard to read. The language fixes every one of these steps, so every JVM gives 5. A reader still has to work it out, so write k++; on a line of its own.

These rules are exact, so the results are the same on every JVM, but code that relies on them is hard to read. Keep ++ and -- in statements of their own, such as count++;, and never change a variable twice in one expression.

Key idea

Precedence only groups an expression; Java then evaluates its operands from left to right, the target of an assignment first, so k = k++ stores the old value of k back into it.

Checkpoint

Check: Evaluation order and side effects

  1. Question 1 of 2 int i = 5; is followed by int j = i++ * 2 + i;. What is j?

    Type a number.

    A hint

    The left operand is evaluated first, and i++ yields the old value.

    Show the answer: Question 1 of 2

    Answer: 16

    i++ yields 5 and makes i 6. Then 5 * 2 is 10, and the last i is read after the increment, so it is 6: 10 + 6 = 16.

  2. Question 2 of 2 int[] a = {0, 0, 0}; int i = 0; is followed by a[i++] = i;. What is a afterwards?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: [1, 0, 0]

    An assignment evaluates its target, index included, before its right side. a[i++] picks a[0] and leaves i at 1; the right side then reads 1, so a[0] becomes 1. seats[index] = index = 2 in Order.java follows the same rule.

Short-circuit operators skip the right operand when the left decides

&& looks at its right operand only if the left one came out true, and || only if it came out false. That makes them guards: s != null && !s.isBlank() never calls a method on null, because when s is null the left side is already false. The first two lines of ShortCircuit in the session above show both operators at work. Step through hasText for its three strings, then the same test written with &:

Interactive · stage by stage How && decides hasText for three strings Step through hasText("Asha"), hasText(" ") and hasText(null), then the same test written with &.
How && decides hasText for three strings, step 5 of 5. Showing s != null (false for null), !s.isBlank() (runs anyway with &), The result (false for null). In focus: !s.isBlank().false: right side skippeds != nullfalse for null!s.isBlank()runs anyway with &The resultfalse for null

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. Asha, the left side. hasText("Asha") checks its left operand first. s != null is true, so the left side has not decided the answer, and && goes on to the right one.
  2. Asha, the right side. !s.isBlank() is true for "Asha", so the result is true, the first word the run printed.
  3. Three spaces. For three spaces the left side is true again, but isBlank() is true, so !s.isBlank() is false and so is the result, the second word of the run.
  4. null. For null the left side is false, and a false left side decides &&. The right side is never evaluated, so no method is called on null, and the result is false.
  5. & has no shortcut. name != null & !name.isEmpty() uses &, which always evaluates both sides. With name null the right side runs anyway and throws NullPointerException, the last line of the run.

& and | also work on booleans and give the same results, but they always evaluate both sides. The last line of ShortCircuit uses &, so name.isEmpty() runs on a null and throws NullPointerException. The message names what was null; it calls the variable <local1> because java File.java compiles without the debugging information that holds local names, and a class compiled with javac -g shows name instead. Use && and || for conditions, and keep & and | for bit masks, the subject of the next lesson.

Checkpoint

Check: Short-circuit && and ||

  1. Question 1 of 2 count is 0 and total is 50. What does count != 0 && total / count > 5 give?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: false, and the division never runs

    && is a guard: put the check that makes the right side safe on the left. With count 0, count != 0 is false and the division is skipped.

  2. Question 2 of 2 Which operator always evaluates both of its boolean operands?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: &

    & and | evaluate both sides; && and || evaluate the right side only when the left one has not decided the result.

A conditional expression takes its type from both branches

condition ? a : b, the conditional operator: The operator condition ? a : b, which evaluates a when the condition is true and b otherwise. Its type comes from both branches, so true ? 1 : 2.0 is the double 1.0., evaluates a when the condition is true and b otherwise. Its type comes from both branches, and that has consequences:

Ternary.java and TernaryNull.java

Java (Ternary.java) · Ternary.java

// The type of a conditional expression comes from both of its branches.
void main() {
    IO.println(true ? 1 : 2.0);   // int and double: the result is a double
    int code = 98;
    IO.println(true ? 'a' : 0);   // char and an int constant that fits in a char: a char
    IO.println(true ? 'a' : code); // char and an int variable: an int
    Object either = true ? 1 : "one";
    IO.println(either.getClass().getSimpleName());
    int score = 72;
    String grade = score >= 90 ? "A" : score >= 75 ? "B" : score >= 60 ? "C" : "D";
    IO.println("grade " + grade);
}

Java (TernaryNull.java) · TernaryNull.java

// A cached value that is missing makes this line throw, although the variable could hold null.
void main() {
    Map<String, Integer> stock = new HashMap<>();
    boolean cached = true;
    Integer count = cached ? stock.get("pens") : 0;
    IO.println(count);
}
The type of ?:, then a NullPointerException from unboxing Python · ternary_session.py
from session import run, version

version()
run("""
java Ternary.java
!java TernaryNull.java
""")

Output

# openjdk version "25.0.4.1" LTS
$ java Ternary.java
1.0
a
97
Integer
grade C
$ java TernaryNull.java
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because the return value of "java.util.Map.get(Object)" is null
	at TernaryNull.main(TernaryNull.java:5)
[exit status 1]

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 ternary_session.py

  • true ? 1 : 2.0 prints 1.0: with an int and a double branch the whole expression is a double.
  • true ? 'a' : 0 prints a, but true ? 'a' : code prints 97. A char paired with an int constant that fits in a char stays a char; paired with an int variable it becomes an int.
  • Branches of unrelated types, such as 1 and "one", make it a reference expression: the 1 is boxed, so the value here is an Integer.
  • A chain such as score >= 90 ? "A" : score >= 75 ? "B" : ... groups from the right, so it reads like a ladder of else if. Past two or three steps, an if or a switch is clearer.
  • In TernaryNull, one branch is an Integer and the other the int 0, so the expression’s type is int, and the Integer is Turning a wrapper object such as Integer into its primitive value, an int here. Java does it on its own where a primitive is needed, and unboxing null throws NullPointerException.. stock.get("pens") returns null, and unboxing null throws, even though the variable on the left could hold null. Write Integer.valueOf(0) in the second branch, or use stock.getOrDefault("pens", 0).

The branches decide the type, and the type decides what is printed. The run’s five lines, by the pair of branches:

The two branches The type of ?: The run printed
1 and 2.0 double 1.0
'a' and the constant 0 char a
'a' and the int variable code int 97
1 and "one" a reference, with 1 boxed Integer
stock.get("pens") and 0 int, so the Integer is unboxed NullPointerException

Checkpoint

Check: The type of a conditional expression

  1. Question 1 of 2 What does this print?

    Read the code, then choose one answer.

    IO.println(false ? 'x' : 120);
    Show the answer: Question 1 of 2

    Answer: x

    The type of ?: comes from both branches. 'x' is a char and 120 a constant that fits in a char, so the whole is a char; 120 is the code of x. With an int variable instead of 120 it would print 120.

  2. Question 2 of 2 flag is a boolean. What is the type of flag ? 1 : 2.5?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: double

    With numeric branches the conditional expression takes the wider type, here double, so flag ? 1 : 2.5 is 1.0 when flag is true.

String concatenation groups from the left, so sums need parentheses

When either operand of + is a String, + joins text instead of adding. It still groups from the left, so 1 + 2 + "3" adds 1 and 2 first and then joins, giving "33", while "1" + 2 + 3 joins at every step and gives "123", the last two lines of the twelve:

The expression Grouped as Result
1 + 2 + "3" (1 + 2) + "3": 3, then "33" "33"
"1" + 2 + 3 ("1" + 2) + 3: "12", then "123" "123"

The common bug is "Total: " + a + b, which prints the two numbers side by side. Put arithmetic inside a string expression in parentheses: "Total: " + (a + b).

== deserves one sentence here too: on primitive values it compares the values, but on objects it compares references, so two different String objects with the same text are not ==. The lessons on strings and wrapper classes later in this module show what to use instead.

Checkpoint

Check: String + and parentheses

  1. One question What are "" + 1 + 2 and 1 + 2 + ""?

    Choose one answer.

    Show the answer: One question

    Answer: "12" and "3"

    + groups from the left, and each step is a join once either operand is a String: ("" + 1) + 2 is "12", while (1 + 2) + "" is "3".

Practise: five bugs from this module

Each method below compiles and runs, and each has one bug of a kind this lesson and the integer arithmetic lesson describe: precedence, string +, the order of a short-circuit guard, the sign of % and integer division. Fix them:

Bugs.java Java
// Exercise: each of these five methods compiles and runs, and each has one bug from this module. Fix them, then
// run this file: every check must say ok.
double average(int a, int b) {
    return a + b / 2.0;
}

String label(int count) {
    return "Items: " + count + 1;           // the label shows the next count
}

int safeLength(String s) {
    return s.length() > 0 && s != null ? s.length() : 0;
}

boolean isOdd(int n) {
    return n % 2 == 1;
}

int percent(int part, int whole) {
    return part / whole * 100;
}

int failures = 0;

void check(String what, boolean passed) {
    if (!passed) failures++;
    IO.println((passed ? "ok      " : "FAILED  ") + what);
}

boolean safeLengthOfNullIsZero() {
    try {
        return safeLength(null) == 0;
    } catch (NullPointerException e) {
        return false;
    }
}

void main() {
    check("average(3, 6) is 4.5", average(3, 6) == 4.5);
    check("label(9) is \"Items: 10\"", label(9).equals("Items: 10"));
    check("safeLength(\"abc\") is 3", safeLength("abc") == 3);
    check("safeLength(null) is 0", safeLengthOfNullIsZero());
    check("isOdd(7) and isOdd(-7)", isOdd(7) && isOdd(-7));
    check("percent(45, 60) is 75", percent(45, 60) == 75);
    IO.println(failures + " of 6 checks failed");
    if (failures > 0) System.exit(1);
}

As given, five of the six checks fail:

The exercise before you start Python · exercise_session.py
from session import run, version

version()
run("""
!java Bugs.java
""")

Output

# openjdk version "25.0.4.1" LTS
$ java Bugs.java
FAILED  average(3, 6) is 4.5
FAILED  label(9) is "Items: 10"
ok      safeLength("abc") is 3
FAILED  safeLength(null) is 0
FAILED  isOdd(7) and isOdd(-7)
FAILED  percent(45, 60) is 75
5 of 6 checks failed
[exit status 1]

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 exercise_session.py

First hint: read each return line and add the parentheses Java uses. a + b / 2.0 is a + (b / 2.0), and s.length() > 0 && s != null calls length() before it checks for null.

With the six checks passing, try the questions below: grouping, the order of side effects, guards, the type of ?: and string +. Your first answer to each one sets how hard the next is on that idea:

Practice that adapts to you

Practise this lesson

15 questions about 5 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 15 After int a, b; a = b = 7 + 1;, what are a and b?

    Choose one answer.

    Show the answer: Question 1 of 15

    Answer: Both are 8

    Assignment groups from the right: b = 7 + 1 runs first and yields 8, which is then assigned to a.

  2. Question 2 of 15 What is the value of 20 - 6 / 2 * 3 + 4 % 3?

    Type a number.

    Show the answer: Question 2 of 15

    Answer: 12

    /, * and % bind tighter than + and -, and each level groups from the left: 6 / 2 is 3, 3 * 3 is 9, 4 % 3 is 1. Then 20 - 9 + 1, from the left, is 12.

  3. Question 3 of 15 A check is written if (low < x < high) with three ints. What happens?

    Choose one answer.

    Show the answer: Question 3 of 15

    Answer: It does not compile: low < x is a boolean, which cannot be compared with high

    javac reports bad operand types for binary operator '<', with first type boolean and second type int. Write low < x && x < high.

  4. Question 4 of 15 What value does the expression i++ have, if i holds 5 just before?

    Choose one answer.

    Show the answer: Question 4 of 15

    Answer: 5, and i holds 6 afterwards

    i++ yields 5 and leaves i at 6; ++i would yield 6. That old value is what k = k++ stores back into k.

  5. Question 5 of 15 What does this print?

    Read the code, then choose one answer.

    int i = 3;
    i = i++ + ++i;
    IO.println(i);
    Show the answer: Question 5 of 15

    Answer: 8

    Operands are evaluated from the left. i++ yields 3 and makes i 4; ++i makes i 5 and yields 5. The sum, 3 + 5 = 8, is then assigned to i.

  6. Question 6 of 15 show("a", 1) + show("b", 2) * show("c", 3) prints a line from each call. In which order do the lines appear?

    Choose one answer.

    Show the answer: Question 6 of 15

    Answer: a, b, c

    Precedence groups the expression as a + (b * c), but Java still evaluates a, then b, then c, and only then multiplies and adds.

  7. Question 7 of 15 When does && evaluate its right operand?

    Choose one answer.

    Show the answer: Question 7 of 15

    Answer: Only when the left operand is true

    && evaluates its right side only when the left is true; || only when the left is false. That is what makes s != null && !s.isBlank() safe.

  8. Question 8 of 15 s may be null. Which condition never throws NullPointerException?

    Choose one answer.

    Show the answer: Question 8 of 15

    Answer: s != null && s.length() > 3

    && evaluates its right operand only when the left one is true, so length() is called only on a string that is not null. The second choice calls length() first; & and | always evaluate both sides.

  9. Question 9 of 15 boolean ok = cacheHit() || loadFromDisk(); and cacheHit() returns true. Does loadFromDisk() run?

    Choose one answer.

    Show the answer: Question 9 of 15

    Answer: No, because a true left side decides ||

    With ||, a true left side means the result is true whatever the right side would give, so Java does not call loadFromDisk(). Any side effects of the right operand happen only when it runs.

  10. Question 10 of 15 What does IO.println(true ? 1 : 2.0); print?

    Choose one answer.

    Show the answer: Question 10 of 15

    Answer: 1.0

    Ternary.java printed 1.0 for exactly this line: the type of ?: comes from both branches.

  11. Question 11 of 15 What does IO.println(false ? 1.0 : 7); print?

    Choose one answer.

    Show the answer: Question 11 of 15

    Answer: 7.0

    One branch is a double, so the whole conditional expression is a double, and the int 7 is widened to 7.0 even though the double branch is not chosen.

  12. Question 12 of 15 What does this print?

    Read the code, then choose one answer.

    int code = 120;
    IO.println(false ? 'x' : code);
    Show the answer: Question 12 of 15

    Answer: 120

    A char paired with an int constant that fits in a char stays a char; paired with an int variable, the expression becomes an int. That is why Ternary.java printed a for 'a' : 0 and 97 for 'a' : code.

  13. Question 13 of 15 What is "1" + 2 + 3?

    Choose one answer.

    Show the answer: Question 13 of 15

    Answer: "123"

    + groups from the left: "1" + 2 is "12", and "12" + 3 is "123", as the last line of Precedence.java printed.

  14. Question 14 of 15 What does this print?

    Read the code, then choose one answer.

    int a = 4, b = 5;
    IO.println("Sum: " + a + b);
    IO.println(a + b + " is the sum");
    Show the answer: Question 14 of 15

    Answer: "Sum: 45", then "9 is the sum"

    + groups from the left. In the first line the left operand is already a String, so both numbers are joined as text. In the second, a + b is computed first as numbers, 9, and only then joined.

  15. Question 15 of 15 What does this print?

    Read the code, then choose one answer.

    IO.println('a' + 'b' + "c");
    Show the answer: Question 15 of 15

    Answer: 195c

    + groups from the left, and two chars add as numbers: 'a' + 'b' is 195, as Chars.java in the casting lesson printed. 195 + "c" is then the String 195c.

Interview questions

Fresher · What is the difference between & and && in Java?

Both give the logical AND of two boolean values. The difference is that && stops early: if the left operand is false, the right one is never evaluated, which is why s != null && s.isEmpty() cannot throw. & always evaluates both operands, so the same expression with & throws NullPointerException when s is null, and side effects on the right always happen. & also works on integers as a bitwise AND, which && does not. Use && in conditions and & for bit masks.

Key takeaways

  • Precedence decides grouping: * / % before + -, then shifts, comparisons, equality, &, ^, |, &&, ||, ?: and assignment; most binary operators group from left to right, assignment and ?: from right to left.
  • Operands are always evaluated from left to right, whatever the grouping, and k = k++ leaves k unchanged.
  • && and || skip their right operand when the left one decides the result; put the null check first.
  • The type of ?: comes from both branches: true ? 1 : 2.0 is 1.0, and an Integer branch next to an int is unboxed, which throws for null.
  • String + groups from the left, so "Total: " + (a + b) needs its parentheses.

Terms in this lesson

associativity
The rule that groups a chain of operators of the same precedence: most binary operators group from the left, so 10 - 4 - 3 is (10 - 4) - 3, while assignment and ?: group from the right, so a = b = 8 assigns b first.
conditional operator
The operator condition ? a : b, which evaluates a when the condition is true and b otherwise. Its type comes from both branches, so true ? 1 : 2.0 is the double 1.0.
operator precedence
The rule that decides how an expression with several operators is grouped: * binds tighter than +, so 1 + 2 * 3 is 1 + (2 * 3). Parentheses override it, and it never changes the left-to-right order of evaluation.
short-circuit evaluation
How && and || work: the right operand is evaluated only when the left one has not decided the result, so s != null && s.isEmpty() never calls a method on null. & and | always evaluate both sides.

References

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.