Skip to content
Dev Dump

πŸ”Ή Part 11: Output-Based Java Questions

Output-based questions are high-frequency interview favorites, especially in online assessments and coding rounds. They test:

  • Deep understanding of execution order
  • Tricky edge cases with inheritance, static blocks, overloading, etc.
  • Mastery of Java quirks beyond syntax
  • Memory management and object lifecycle
  • Exception handling scenarios
class Test {
static {
System.out.println("Static Block 1");
}
static {
System.out.println("Static Block 2");
}
public static void main(String[] args) {
System.out.println("Main Method");
}
}
Static Block 1
Static Block 2
Main Method

πŸ” Key Points:

  • Static blocks run once when the class is loaded, before the main() method
  • Multiple static blocks execute in order of appearance
  • Static blocks run even if main() is never called
public class Test {
public static void main(String args) {
System.out.println("Overloaded main with String");
}
public static void main(String[] args) {
System.out.println("Main Method with String array");
}
public static void main(int[] args) {
System.out.println("Main Method with int array");
}
public static void main() {
System.out.println("Main Method with no args");
}
}
Main Method with String array

πŸ” Key Points:

  • Only the signature public static void main(String[] args) is treated as the entry point by JVM
  • Other overloaded versions are just regular methods
  • JVM looks for the exact signature, not the most specific one

πŸ§ͺ Example 3: Static Method Hiding vs Method Overriding

Section titled β€œπŸ§ͺ Example 3: Static Method Hiding vs Method Overriding”
class Parent {
static void display() {
System.out.println("Parent static method");
}
void show() {
System.out.println("Parent instance method");
}
}
class Child extends Parent {
static void display() {
System.out.println("Child static method");
}
@Override
void show() {
System.out.println("Child instance method");
}
}
public class Main {
public static void main(String[] args) {
Parent p = new Child();
p.display(); // Static method - resolved at compile time
p.show(); // Instance method - resolved at runtime
Child c = new Child();
c.display(); // Child's static method
c.show(); // Child's instance method
}
}
Parent static method
Child instance method
Child static method
Child instance method

πŸ” Key Points:

  • Static methods are resolved at compile time based on reference type (method hiding)
  • Instance methods are resolved at runtime based on actual object type (method overriding)
  • This is a classic interview question to test understanding of static vs dynamic binding

πŸ§ͺ Example 4: finally vs return - Tricky Scenarios

Section titled β€œπŸ§ͺ Example 4: finally vs return - Tricky Scenarios”
public class Test {
public static int getValue1() {
try {
return 1;
} finally {
return 2;
}
}
public static int getValue2() {
try {
return 1;
} finally {
System.out.println("Finally block executed");
// No return in finally
}
}
public static int getValue3() {
try {
throw new RuntimeException("Exception");
} finally {
return 3;
}
}
public static void main(String[] args) {
System.out.println("getValue1(): " + getValue1());
System.out.println("getValue2(): " + getValue2());
System.out.println("getValue3(): " + getValue3());
}
}
getValue1(): 2
Finally block executed
getValue2(): 1
getValue3(): 3

πŸ” Key Points:

  • finally block always executes (except System.exit())
  • If finally has a return, it overrides the try block’s return
  • If finally has no return, the try block’s return value is preserved
  • finally can suppress exceptions if it has a return

πŸ§ͺ Example 5: Null and Method Overloading - Advanced Cases

Section titled β€œπŸ§ͺ Example 5: Null and Method Overloading - Advanced Cases”
class A {
void method(Object o) {
System.out.println("Object method");
}
void method(String s) {
System.out.println("String method");
}
void method(Integer i) {
System.out.println("Integer method");
}
void method(String... strings) {
System.out.println("Varargs String method");
}
public static void main(String[] args) {
A a = new A();
a.method(null); // Ambiguous - String vs Integer
a.method((Object) null); // Object method
a.method((String) null); // String method
a.method((Integer) null); // Integer method
}
}
Compilation error: reference to method is ambiguous

πŸ” Key Points:

  • null can be assigned to any reference type
  • When multiple overloaded methods can accept null, Java can’t determine which one to call
  • Most specific type wins when there’s no ambiguity
  • Explicit casting resolves ambiguity

πŸ§ͺ Example 6: Constructor Chaining and Initialization Order

Section titled β€œπŸ§ͺ Example 6: Constructor Chaining and Initialization Order”
class A {
static { System.out.println("A static block"); }
{ System.out.println("A instance block"); }
A() {
System.out.println("A constructor");
}
}
class B extends A {
static { System.out.println("B static block"); }
{ System.out.println("B instance block"); }
B() {
System.out.println("B constructor");
}
}
class C extends B {
static { System.out.println("C static block"); }
{ System.out.println("C instance block"); }
C() {
System.out.println("C constructor");
}
}
public class Test {
public static void main(String[] args) {
System.out.println("Creating C object:");
new C();
System.out.println("\nCreating another C object:");
new C();
}
}
A static block
B static block
C static block
Creating C object:
A instance block
A constructor
B instance block
B constructor
C instance block
C constructor
Creating another C object:
A instance block
A constructor
B instance block
B constructor
C instance block
C constructor

πŸ” Key Points:

  • Static blocks execute once per class when class is loaded
  • Instance blocks execute before each constructor
  • Constructor chaining: super() β†’ instance blocks β†’ constructor body
  • Static blocks run in parent β†’ child order
  • Instance blocks run in parent β†’ child order

πŸ§ͺ Example 7: Exception in Static Block and Class Loading

Section titled β€œπŸ§ͺ Example 7: Exception in Static Block and Class Loading”
class Test {
static {
System.out.println("Static block 1");
try {
int a = 5 / 0;
} catch (Exception e) {
System.out.println("Caught exception in static block: " + e.getMessage());
}
}
static {
System.out.println("Static block 2");
}
public static void main(String[] args) {
System.out.println("Main method");
}
}
Static block 1
Caught exception in static block: / by zero
Static block 2
Main method

πŸ” Key Points:

  • Exception in static block doesn’t always prevent class loading
  • If exception is caught, class loading continues
  • If exception is uncaught, class loading fails and main() never executes
  • ErrorInInitializerError is thrown for uncaught exceptions in static blocks
public class StringTest {
public static void main(String[] args) {
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
String s4 = new String("Hello");
System.out.println("s1 == s2: " + (s1 == s2)); // true
System.out.println("s1 == s3: " + (s1 == s3)); // false
System.out.println("s3 == s4: " + (s3 == s4)); // false
System.out.println("s1.equals(s3): " + s1.equals(s3)); // true
String s5 = "Hello" + "World";
String s6 = "HelloWorld";
System.out.println("s5 == s6: " + (s5 == s6)); // true (compile-time concatenation)
String s7 = s1 + "World";
String s8 = "HelloWorld";
System.out.println("s7 == s8: " + (s7 == s8)); // false (runtime concatenation)
}
}
s1 == s2: true
s1 == s3: false
s3 == s4: false
s1.equals(s3): true
s5 == s6: true
s7 == s8: false

πŸ” Key Points:

  • String literals are stored in String Pool
  • new String() creates new objects in heap
  • Compile-time concatenation creates pooled strings
  • Runtime concatenation creates new objects
  • == compares references, equals() compares content
public class AutoboxingTest {
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println("i1 == i2: " + (i1 == i2)); // true
System.out.println("i3 == i4: " + (i3 == i4)); // false
Boolean b1 = true;
Boolean b2 = true;
System.out.println("b1 == b2: " + (b1 == b2)); // true
Character c1 = 'A';
Character c2 = 'A';
System.out.println("c1 == c2: " + (c1 == c2)); // true
Long l1 = 100L;
Long l2 = 100L;
System.out.println("l1 == l2: " + (l1 == l2)); // true
}
}
i1 == i2: true
i3 == i4: false
b1 == b2: true
c1 == c2: true
l1 == l2: true

πŸ” Key Points:

  • Integer cache: -128 to 127 (inclusive) are cached
  • Boolean, Character, Long have similar caching for small values
  • Always use equals() for wrapper class comparisons
  • == works for cached values but fails for others
public class ThreadTest {
public static void main(String[] args) {
System.out.println("Main thread: " + Thread.currentThread().getName());
Thread t1 = new Thread(() -> {
System.out.println("Thread 1: " + Thread.currentThread().getName());
});
Thread t2 = new Thread(() -> {
System.out.println("Thread 2: " + Thread.currentThread().getName());
});
t1.start();
t2.start();
System.out.println("Main thread ending");
}
}
Main thread: main
Main thread ending
Thread 1: Thread-0
Thread 2: Thread-1

πŸ” Key Points:

  • Thread execution order is not guaranteed
  • Main thread may complete before or after other threads
  • Thread scheduling is controlled by OS
  • join() can be used to wait for thread completion
TrickHow to Handle
finally overriding returnMention explicitly
null method overloadingLook for the most specific type
Static vs instanceKnow which resolves at compile vs runtime
Constructor chainTrace parent β†’ child
main() variantsJVM only calls main(String[] args)
String pool behaviorUnderstand literal vs new String()
Autoboxing cacheKnow the cached ranges
Thread execution orderOrder is not guaranteed
Exception in static blocksCheck if caught or uncaught
  1. Static vs Instance: Always check if method is static or instance
  2. Null handling: Look for null pointer scenarios
  3. Exception flow: Trace exception handling carefully
  4. Object lifecycle: Understand when objects are created/destroyed
  5. Memory management: Know about string pool, autoboxing cache
  6. Thread behavior: Remember thread execution is unpredictable
  7. Constructor chaining: Always trace parent β†’ child order
  8. Method resolution: Static at compile time, instance at runtime