Java Expressions and Code Tracing, CS312 – Study Notes
offline

Difficulty: Foundational | Prerequisites: Basic Java syntax, data types, operators

Big Picture

Expression evaluation and code tracing form the bedrock of CS312. Every other topic in the course, from arrays to inheritance, assumes you can look at a line of Java and know exactly what it produces. If you cannot trace through code on paper without a compiler, the exam will punish you for it. This material draws on your knowledge of primitive types, operator precedence, and basic object-oriented syntax.


TL;DR

Java expressions combine integer arithmetic, type promotion, casting, string concatenation, and boolean logic, and you need to evaluate them left to right respecting precedence. Code tracing means reading through loops, arrays, and class hierarchies by hand to predict output, spot runtime errors, or identify infinite loops and syntax errors.

Key Terms

Integer division (truncation)

When both operands are int, Java discards the decimal portion entirely. 14 / 3 gives 4, not 4.666.... No rounding occurs.

In simple terms, Java chops off everything after the decimal point when dividing two whole numbers.

Type promotion (widening conversion)

When an int and a double appear in the same arithmetic expression, Java automatically converts the int to a double before performing the operation. The result is a double.

Think of it as Java upgrading the smaller type so both sides match.

Explicit casting

Forcing a value into a different type by writing the target type in parentheses, e.g. (int) 3.9 produces 3. Casting a double to int truncates; casting an int to char gives the character at that Unicode code point.

In simple terms, you are telling Java "treat this value as that type, even if it loses information."

String concatenation with +

When one operand of + is a String, Java converts the other operand to a String and joins them. Evaluation proceeds left to right, so 3 + 4 + "hello" gives "7hello", not "34hello".

Think of it as: once Java sees a String on either side of +, everything from that point onward becomes string gluing.

Math.random()

Returns a double in the range [0.0, 1.0), meaning it can be 0.0 but is always strictly less than 1.0. This matters for boolean comparisons: Math.random() < 1.0 is always true, and Math.random() >= 1.0 is always false.

Operator precedence

The order in which Java evaluates operators when no parentheses dictate otherwise. Multiplication and division bind before addition and subtraction. Assignment (=) has the lowest precedence. When operators share the same level, evaluation runs left to right.

Boolean short-circuit evaluation

With &&, if the left side is false, Java skips the right side entirely. With ||, if the left side is true, Java skips the right side. This can prevent runtime errors (e.g. avoiding a null check on the right side) and affects tracing questions.


Core Content: Expression Evaluation

Integer arithmetic

  • 14 / 3 gives 4 (truncation, not rounding)

  • 14 % 3 gives 2 (the remainder)

  • Mixing int and double promotes the result to double: 7 / 2.0 gives 3.5

Character arithmetic

  • A char is stored as a numeric Unicode value. 'A' is 65, 'B' is 66, and so on.

  • Arithmetic on chars produces an int: 'A' + 3 gives 68 (an int), not 'D'

  • To get a char result, cast explicitly: (char)('A' + 3) gives 'D'

String concatenation order

  • Evaluation runs left to right. Arithmetic happens normally until a String appears, after which + becomes concatenation.

  • 3 + 4 + "hello" evaluates as (3 + 4) + "hello" = "7hello"

  • "hello" + 3 + 4 evaluates as ("hello" + 3) + 4 = "hello34"

  • The empty string "" is a valid String. Concatenating anything to it produces a String version of that value.

Boolean expressions

  • Comparisons return boolean (true/false). The result of == on reference types checks identity (same object), not value equality.

  • Math.random() returns [0.0, 1.0), so Math.random() < 1.0 is always true and Math.random() >= 1.0 is always false.

Casting pitfalls

  • (int) on a double truncates toward zero: (int) 5.9 gives 5, (int) -2.7 gives -2

  • Casting does not round. Students who write "6" for (int) 5.6 lose the mark.


Core Content: Code Tracing Patterns

Array tracing

  • Track each index and its value after every assignment. Draw a table with columns for each index.

  • Watch for off-by-one errors in loop bounds: i < arr.length vs. i <= arr.length (the latter causes ArrayIndexOutOfBoundsException).

  • When arrays are passed to methods, changes to elements inside the method affect the original array (arrays are reference types).

Common output patterns

  • Array output format on the exam: [3, 4, 8] with square brackets and commas

  • Multiple print statements vs. println: know whether output lands on the same line or a new one

  • Numeric output: 4 8 0.0 means three separate printed values. The 0.0 signals a double, not an int.

Runtime errors to recognise

  • ArithmeticException: division by zero with integers (x / 0 where x is int). Division by zero with double does not crash; it produces Infinity or NaN.

  • ArrayIndexOutOfBoundsException (AIOBE): accessing an index outside [0, length - 1]

  • NullPointerException (NPE): calling a method or accessing a field on a null reference

  • StackOverflowError: infinite recursion

Infinite loops

  • A while loop whose condition never becomes false. Common causes: forgetting to increment a counter, or a boolean expression that is always true by construction.

  • The exam expects you to write "INFINITE LOOP" rather than guessing at output.

Inheritance and polymorphism tracing

  • The declared type determines which methods are visible at compile time. If the declared type is Computer and Computer has no getColors() method, calling getColors() is a syntax error, even if the runtime type is a subclass that defines it.

  • The runtime type determines which version of an overridden method runs. Casting does not change the object, only the compiler's view of it.

  • Subtype checks: PC extends Computer means a PC reference can go into a Computer variable, but not the reverse without a cast. Assigning the wrong way is a syntax error.

Access modifiers in tracing

  • private instance variables cannot be accessed outside their own class, not even by subclasses.

  • If a tracing question asks "why does this fail?", the answer is often that a private field is being accessed from outside its class.


Common Misconceptions

  • Students often think (int) 5.6 rounds to 6. It does not. Casting to int always truncates toward zero.

  • Students often think 3 + 4 + "hello" produces "34hello". It does not. The 3 + 4 is evaluated first as integer addition because no String is involved yet, giving 7, and then 7 + "hello" concatenates.

  • Students often confuse a compile-time error (syntax error) with a runtime error. A syntax error means the code will not compile at all. A runtime error means it compiles but crashes while running.

  • Students often think that because a subclass has a method, you can call it through a superclass reference. You cannot. The declared type controls what the compiler allows.


Quick Self-Test

  1. True or False: (int) 9.99 evaluates to 10. (False, it evaluates to 9.)

  1. True or False: "" + 5 + 3 evaluates to "53". (True. The empty string makes both + operations concatenation.)

  1. Fill in the blank: Math.random() returns a value in the range ____. ([0.0, 1.0) , inclusive of 0.0, exclusive of 1.0.)

  1. True or False: Dividing an int by 0 causes a compile-time error. (False. It compiles but throws ArithmeticException at runtime.)

  1. True or False: If Dog extends Animal, you can assign an Animal variable to a Dog variable without a cast. (False. You need an explicit cast, and it may throw ClassCastException at runtime.)


Practice Q&A

Q: What is the result of the expression 2 + 3 * 4 - 1?

A: 13. Multiplication first: 3 * 4 = 12. Then left to right: 2 + 12 - 1 = 13.

Q: What does "RING" + 5 + 5 evaluate to?

A: "RING55". The first + sees a String on the left, so 5 is concatenated as "RING5". The second + also concatenates: "RING55".

Q: What is the output of the following code? int[] arr = {1, 2, 3}; arr[1] = arr[0] + arr[2]; System.out.println(Arrays.toString(arr));

A: [1, 4, 3]. arr[0] + arr[2] is 1 + 3 = 4, stored at index 1.

Q: A variable cp is declared as type Computer. The object it refers to is a Mac (which extends Computer). Mac defines a method getColors() that Computer does not. What happens when you call cp.getColors()?

A: Syntax error (compile-time error). The declared type is Computer, which has no getColors() method. The compiler does not look at the runtime type.

Q: What happens when the following executes? int x = 10; int y = 0; System.out.println(x / y);

A: Runtime error (ArithmeticException: / by zero). Integer division by zero crashes the program.


Related Terms / Search Tags

Java expressions, code tracing, integer division, truncation, type promotion, widening conversion, explicit casting, narrowing conversion, string concatenation, operator precedence, Math.random, boolean short-circuit, ArithmeticException, ArrayIndexOutOfBoundsException, NullPointerException, infinite loop, compile-time error vs runtime error, syntax error, declared type vs runtime type, polymorphism, access modifiers, private fields, CS312 UT Austin, credit by exam, Java fundamentals