beginner18 min

Operators, Expressions, and Working with Strings

Arithmetic, comparison, and logical operators, and the String methods you'll reach for constantly — plus the immutability trap that catches every beginner once.

What you'll learn

  • Use arithmetic, comparison, and logical operators to build correct expressions
  • Explain integer division and operator precedence pitfalls
  • Use core String methods to inspect, transform, and combine text without mutating the original

Prerequisites

Explanation

Java's arithmetic, comparison, and logical operators look familiar from most C-family languages, with one sharp edge worth learning early: integer division truncates. 7 / 2 evaluates to 3, not 3.5 — because both operands are int, Java performs integer division and discards the remainder entirely (use 7 % 2 to get that remainder, 1). The fix, when you want a real fractional result, is to make at least one operand a floating-point type: 7 / 2.0 evaluates to 3.5. This single rule causes more silent, wrong-answer bugs in beginner Java code than almost anything else, precisely because it never throws an error — it just quietly gives you the wrong number.

Comparison operators (==, !=, <, >, <=, >=) work as expected on primitives, but as the previous lesson noted, == on reference types (including String) compares identity, not content — new String("cat") == new String("cat") is false, even though the text is identical, because they're two distinct objects. Comparing String content correctly requires .equals(): "cat".equals(otherString). Logical operators && and || short-circuit: in a() && b(), if a() returns false, b() is never called at all — a behavior you can rely on to safely guard against errors, e.g. list != null && list.size() > 0 never calls .size() on a null reference, because && stops evaluating the moment the left side is false.

Strings, being immutable, expose a rich set of methods that all return a new String rather than modifying the original: .length(), .substring(start, end), .indexOf(text), .toUpperCase()/.toLowerCase(), .trim()/.strip(), .replace(old, new), .split(delimiter), and .equals()/.equalsIgnoreCase() for content comparison. For building a String piece by piece — especially inside a loop — use StringBuilder instead of repeated + concatenation: each + on Strings silently creates a brand-new String object, so concatenating in a loop with + is quadratic in the number of iterations, while StringBuilder.append() grows an internal, mutable buffer in place.

Example

Integer-division truncation, modeled with Math.trunc since JS division is always floating-point.

function javaIntDivide(a, b) {
  return Math.trunc(a / b); // Java's int/int truncates toward zero, just like this
}

console.log(javaIntDivide(7, 2));   // 3, not 3.5
console.log(7 / 2);                  // 3.5 -- what you'd get if either operand were a double
console.log(7 % 2);                  // 1 -- the remainder int division throws away

Try it yourself

Predict javaIntDivide(-7, 2) before running -- Java's truncation rounds toward zero, not toward negative infinity.

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Guided exercise

Guided exercise

Write intDivide(a, b) and remainder(a, b) that model Java's int / and % operators exactly: division truncates toward zero (use Math.trunc), and the remainder has the same sign as the dividend a.

Checks: 7 / 2 == 3 · -7 / 2 == -3 (truncation toward zero) · 7 % 2 == 1 · -7 % 2 == -1

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Independent exercise

Independent exercise

Write contentEquals(s1, s2) modeling Java's String.equals(): true only if both are non-null and have identical characters -- never based on object identity. Then write safeLength(s) modeling short-circuit evaluation: returns s.length if s is not null/undefined, otherwise 0, without throwing.

Checks: equal strings compare equal by content · different strings compare unequal · null never equals a real string · safeLength returns the real length for a real string · safeLength returns 0 for null without throwing

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Common mistakes

  • Writing `int average = (a + b) / 2;` when a fractional average was intended -- integer division silently truncates instead of erroring.
  • Comparing Strings with == instead of .equals() -- it often 'accidentally works' for literal strings due to an implementation detail called string interning, then mysteriously breaks for strings built at runtime (e.g. via concatenation).
  • Concatenating Strings with + inside a loop that runs many times -- each + allocates a new String, making the loop far slower than using StringBuilder.

Knowledge check

Knowledge check

1. What does `int result = 9 / 4;` store in result?
2. Given `String a = new String("cat"); String b = new String("cat");`, what does `a == b` evaluate to?
3. In `if (list != null && list.size() > 0)`, why is this safe even when list might be null?

Takeaway

Integer division truncates and content equality needs .equals(), not ==, on Strings and every other reference type — both are silent, not error-throwing, so they only surface as wrong answers if you don't already know the rule.

Summary

Arithmetic on two ints stays an int and truncates; use a floating-point operand for a fractional result. == compares identity on reference types; .equals() compares content. && and || short-circuit, which is the idiomatic way to guard against null before calling a method.

References

Your notes

Notes save automatically.

Finished this lesson?

Mark it complete to track your progress and schedule a future review.