Java Tricky Programs (Output Prediction)

Naveen AnamaneniUpdated · 8 min read

Every school has a teacher who loves trick questions: "Which is heavier, a kilo of cotton or a kilo of iron?" They aren't meant to fool you for fun; they test whether you really understand the idea or are only pattern-matching. Java interviews have their own trick questions: tiny programs whose output surprises people who haven't looked closely at how Java works. In this lesson, you will work through the most common ones, grouped by topic. Try to predict each answer before opening it, then run the program at the end of each section to check.

How to Approach an Output Question

  1. Read every character. == versus equals, i++ versus ++i, 'A' versus "A" change everything.
  2. Evaluate step by step, left to right, writing down the type of every intermediate value.
  3. Check for compile errors first. Some "what does it print?" questions don't compile at all.
  4. Name the rule in your answer: "Integer caches -128 to 127", not just "false".

Puzzles About Equality

Puzzle 1. What does this print?

Puzzle1.java
Integer a = 127, b = 127;
Integer c = 128, d = 128;
System.out.println(a == b);
System.out.println(c == d);
Show the answer

true, then false. Autoboxing uses Integer.valueOf, which returns cached objects for -128 to 127, so a and b are the same object. 128 is outside the cache, so c and d are two different objects, and == compares references. Always compare wrapper values with equals.

Puzzle 2. What does this print?

Puzzle2.java
String s1 = "Java";
String s2 = "Java";
String s3 = new String("Java");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1 == s3.intern());
Show the answer

true, false, true. Identical string literals share one object from the string pool. new String(...) always creates a new object. intern() returns the pooled copy.

Puzzle 3. What does this print?

Puzzle3.java
System.out.println(0.1 + 0.2 == 0.3);
System.out.println(0.1 + 0.2);
Show the answer

false, then 0.30000000000000004. double stores numbers in binary, and 0.1 and 0.2 have no exact binary form, so tiny rounding errors appear. Use BigDecimal for money, or compare doubles with a small tolerance.

EqualityCheck.java▶ Try it
public class EqualityCheck {
    public static void main(String[] args) {
        Integer a = 127, b = 127;
        Integer c = 128, d = 128;
        System.out.println(a == b);
        System.out.println(c == d);
 
        String s1 = "Java";
        String s2 = "Java";
        String s3 = new String("Java");
        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
        System.out.println(s1 == s3.intern());
 
        System.out.println(0.1 + 0.2 == 0.3);
        System.out.println(0.1 + 0.2);
    }
}
Output
true
false
true
false
true
false
0.30000000000000004

Puzzles About Operators and Types

Puzzle 4. What does this print?

Puzzle4.java
System.out.println(1 + 2 + "3");
System.out.println("1" + 2 + 3);
System.out.println('A' + 1);
System.out.println("" + 'A' + 1);
System.out.println((char) ('A' + 1));
Show the answer

33, 123, 66, A1, B. + works left to right: 1 + 2 is the number 3 before meeting a string. Once a String is involved, + joins text. A char plus an int is an int ('A' is 65), and casting 66 back to char gives B.

Puzzle 5. What does this print?

Puzzle5.java
int i = 0;
i = i++;
System.out.println(i);
Show the answer

0. i++ returns the old value (0) and then increases i to 1, but the assignment i = ... then stores the old value 0 back into i.

Puzzle 6. What does this print?

Puzzle6.java
System.out.println(5 / 2);
System.out.println(5 / 2 * 2.0);
System.out.println(Math.round(-1.5));
System.out.println(Math.round(1.5));
System.out.println((byte) 200);
System.out.println(Math.abs(Integer.MIN_VALUE));
Show the answer

2, 4.0, -1, 2, -56, -2147483648. 5 / 2 is integer division (2) before it is multiplied by 2.0. Math.round rounds half up, towards positive infinity, so -1.5 becomes -1. 200 doesn't fit in a byte (-128 to 127) and wraps to -56. Integer.MIN_VALUE has no positive int counterpart, so abs returns it unchanged.

OperatorCheck.java▶ Try it
public class OperatorCheck {
    public static void main(String[] args) {
        System.out.println(1 + 2 + "3");
        System.out.println("1" + 2 + 3);
        System.out.println('A' + 1);
        System.out.println("" + 'A' + 1);
        System.out.println((char) ('A' + 1));
 
        int i = 0;
        i = i++;
        System.out.println(i);
 
        System.out.println(5 / 2);
        System.out.println(5 / 2 * 2.0);
        System.out.println(Math.round(-1.5));
        System.out.println(Math.round(1.5));
        System.out.println((byte) 200);
        System.out.println(Math.abs(Integer.MIN_VALUE));
    }
}
Output
33
123
66
A1
B
0
2
4.0
-1
2
-56
-2147483648

Puzzles About Methods and Classes

Puzzle 7. Which method is called?

Puzzle7.java
static void show(Object o) { System.out.println("Object"); }
static void show(String s) { System.out.println("String"); }
 
show(null);
Show the answer

String. Both methods accept null, and Java picks the most specific one. String is more specific than Object. If there were also a show(Integer) method, the call would be ambiguous and wouldn't compile.

Puzzle 8. What does this print?

Puzzle8.java
class Parent {
    static String who() { return "Parent"; }
    String name() { return "Parent"; }
}
class Child extends Parent {
    static String who() { return "Child"; }
    String name() { return "Child"; }
}
 
Parent p = new Child();
System.out.println(p.who() + " " + p.name());
Show the answer

Parent Child. Instance methods are overridden and chosen by the object's real type (Child). Static methods are hidden, not overridden, and chosen by the variable's declared type (Parent).

Puzzle 9. What does this method return?

Puzzle9.java
static int value() {
    try {
        return 1;
    } finally {
        return 2;
    }
}
Show the answer

2. The finally block always runs, and a return inside it replaces the return from try. It would even swallow an exception thrown in try. Never return from finally.

MethodCheck.java▶ Try it
public class MethodCheck {
    static void show(Object o) { System.out.println("Object"); }
    static void show(String s) { System.out.println("String"); }
 
    static class Parent {
        static String who() { return "Parent"; }
        String name() { return "Parent"; }
    }
 
    static class Child extends Parent {
        static String who() { return "Child"; }
        @Override String name() { return "Child"; }
    }
 
    @SuppressWarnings("finally")
    static int value() {
        try {
            return 1;
        } finally {
            return 2;
        }
    }
 
    @SuppressWarnings("static-access")
    public static void main(String[] args) {
        show(null);
        Parent p = new Child();
        System.out.println(p.who() + " " + p.name());
        System.out.println(value());
    }
}
Output
String
Parent Child
2

Puzzles About Collections and Strings

Puzzle 10. What does this print?

Puzzle10.java
List<Integer> list = new ArrayList<>(List.of(10, 20, 30));
list.remove(1);
System.out.println(list);
list.remove(Integer.valueOf(10));
System.out.println(list);
Show the answer

[10, 30], then [30]. remove(1) with an int calls remove(int index) and removes the element at index 1 (20). remove(Integer.valueOf(10)) calls remove(Object) and removes the value 10.

Puzzle 11. What does this print?

Puzzle11.java
int[] numbers = {1, 2, 3};
System.out.println(Arrays.asList(numbers).size());
String name = "navika";
name.toUpperCase();
System.out.println(name);
Show the answer

1, then navika. Arrays.asList takes objects, so an int[] becomes a single element (the array itself): use Integer[] or IntStream. Strings are immutable: toUpperCase() returns a new string, which is thrown away here.

CollectionCheck.java▶ Try it
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
 
public class CollectionCheck {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>(List.of(10, 20, 30));
        list.remove(1);
        System.out.println(list);
        list.remove(Integer.valueOf(10));
        System.out.println(list);
 
        int[] numbers = {1, 2, 3};
        System.out.println(Arrays.asList(numbers).size());
        String name = "navika";
        name.toUpperCase();
        System.out.println(name);
    }
}
Output
[10, 30]
[30]
1
navika

Puzzles That Don't Compile

Puzzle 12. Which line fails to compile?

Puzzle12.java
short s = 1;
s += 1;        // line A
s = s + 1;     // line B
Show the answer

Line B. s + 1 is an int, and assigning an int to a short needs a cast. Line A compiles because compound assignment operators such as += include a hidden cast: s += 1 means s = (short) (s + 1).

Puzzle 13. Does this compile?

Puzzle13.java
final int x;
System.out.println(x);
Show the answer

No. A local variable must be definitely assigned before it is read, whether or not it is final. The error is "variable x might not have been initialized".

Interview Corner

Why should you never compare Integer objects with ==?

Because == compares references. It happens to work for values from -128 to 127, which are cached, and fails for others. Use equals or compare int values.

Why is returning from a finally block dangerous?

It replaces any value returned by try or catch and silently discards any exception thrown there, hiding real errors. Compilers warn about it.

Practice

  1. Easy: Predict, then run: System.out.println(10 == 10.0); and System.out.println('a' + 'b');
  2. Harder: Predict, then run: long micros = 24 * 60 * 60 * 1000 * 1000; System.out.println(micros);. Explain the result and fix it with one character.

Quick check: Tricky programs

4 questions
1What does System.out.println(1 + 2 + "3") print?
2After int i = 5; i = i++; what is i?
3Which method runs for show(null) with show(Object) and show(String)?
4What does (byte) 200 give?

Key Takeaways

Was this tutorial helpful?

Lesson 567 of 578