Java Interview Question Answers Part 3

Core Java Interview Questions & Answers – Part 3 (Advanced Basics with Clear Use Cases)


41. What is an abstract class in Java?

Answer: An abstract class is a class that cannot be instantiated on its own and may contain abstract methods (methods without an implementation). It serves as a blueprint for other classes.

Why used: To provide a common base for related classes, enforcing a contract that subclasses must fulfill by implementing abstract methods, while also allowing shared non-abstract methods and fields.

Use case: A Shape abstract class with an abstract area() method, which Circle and Rectangle subclasses must implement.

abstract class Shape {
    abstract double area();
    void display() {
        System.out.println("This is a shape.");
    }
}
class Circle extends Shape {
    double radius;
    Circle(double radius) { this.radius = radius; }
    @Override
    double area() { return Math.PI * radius * radius; }
}

42. What is an interface in Java?

Answer: An interface is a blueprint of a class that specifies a contract for implementing classes. It can only contain method signatures (implicitly public abstract before Java 8), default methods, static methods, and constant fields.

Why used: To achieve full abstraction and multiple inheritance of type (behavior) in Java, defining a set of behaviors that implementing classes must provide.

Use case: A Flyable interface for objects that can fly, implemented by Bird and Airplane classes.

interface Flyable {
    void fly();
    default void takeoff() { // Java 8 default method
        System.out.println("Taking off!");
    }
}
class Bird implements Flyable {
    @Override
    public void fly() { System.out.println("Bird flying."); }
}

43. Difference between abstract class and interface?

Answer:

Feature Abstract Class Interface
Type Class Blueprint of a class
Instantiation Cannot be instantiated Cannot be instantiated
Methods Can have abstract and non-abstract methods Can have abstract, default, static methods (Java 8+)
Variables Can have instance, static, and final variables Can only have public static final variables (constants)
Constructors Can have constructors Cannot have constructors
Multiple Inheritance Not allowed (single inheritance) Allowed (multiple interface implementation)
Access Modifiers Members can have any access modifier All members are implicitly public

Why important: Choosing the right abstraction mechanism for specific design requirements. Abstract classes for "is-a" relationships and shared implementations; interfaces for "has-a" relationships and defining contracts.


44. Explain Polymorphism in Java.

Answer: Polymorphism means "many forms." In Java, it refers to the ability of an object to take on many forms, specifically allowing a single interface to represent different underlying forms (data types). This happens through method overriding (runtime polymorphism) and method overloading (compile-time polymorphism).

Why important: Enables writing flexible, extensible, and reusable code. It allows you to program to an interface, not an implementation.

Use case: Calling a draw() method on a collection of Shape objects, where each Shape subclass implements draw() differently.

class Animal {
    void makeSound() { System.out.println("Animal makes a sound"); }
}
class Dog extends Animal {
    @Override
    void makeSound() { System.out.println("Dog barks"); }
}
class Cat extends Animal {
    @Override
    void makeSound() { System.out.println("Cat meows"); }
}

public class PolymorphismDemo {
    public static void main(String[] args) {
        Animal myAnimal = new Dog(); // Runtime polymorphism
        myAnimal.makeSound(); // Outputs "Dog barks"

        myAnimal = new Cat();
        myAnimal.makeSound(); // Outputs "Cat meows"
    }
}

45. Explain Encapsulation in Java.

Answer: Encapsulation is the mechanism of bundling the data (variables) and the methods (functions) that operate on the data into a single unit (class). It also involves restricting direct access to some of an object's components, typically achieved by making fields private and providing public getter and setter methods.

Why important: Protects data from unauthorized access, allows for better control over data modification, and simplifies code maintenance and reusability by hiding internal implementation details.

Use case: A BankAccount class where the balance is private, and can only be accessed or modified via deposit() and withdraw() methods.

class BankAccount {
    private double balance;

    public BankAccount(double initialBalance) {
        if (initialBalance >= 0) {
            this.balance = initialBalance;
        } else {
            this.balance = 0;
        }
    }

    public double getBalance() { // Getter
        return balance;
    }

    public void deposit(double amount) { // Setter-like method
        if (amount > 0) {
            balance += amount;
            System.out.println("Deposited: " + amount);
        }
    }

    public void withdraw(double amount) { // Setter-like method
        if (amount > 0 && balance >= amount) {
            balance -= amount;
            System.out.println("Withdrew: " + amount);
        } else {
            System.out.println("Insufficient balance or invalid amount.");
        }
    }
}

46. What are Generics in Java?

Answer: Generics allow you to write classes, interfaces, and methods that operate on objects of various types while providing compile-time type safety. They eliminate the need for explicit type casting and prevent ClassCastException at runtime.

Why important: Enables code reuse with different types, improves type safety, and makes code more readable and robust.

Use case: Creating a List that specifically holds String objects, preventing accidental addition of Integer objects.

List<String> names = new ArrayList<>();
names.add("Alice");
// names.add(123); // Compile-time error due to generics
String name = names.get(0); // No casting needed

47. Explain Exception Handling in Java.

Answer: Exception handling is a mechanism to manage runtime errors (exceptions) that disrupt the normal flow of program execution. It uses try, catch, finally, throw, and throws keywords to detect, report, and resolve exceptional conditions.

Why important: Makes programs robust and reliable by gracefully handling unexpected events, preventing application crashes, and allowing for recovery or controlled shutdown.

Use case: Handling ArithmeticException (e.g., division by zero) or FileNotFoundException when working with files.

try {
    int result = 10 / 0; // This will throw an ArithmeticException
    System.out.println(result);
} catch (ArithmeticException e) {
    System.err.println("Error: Cannot divide by zero. " + e.getMessage());
} finally {
    System.out.println("This block always executes.");
}

48. What is try-with-resources?

Answer: try-with-resources is a statement introduced in Java 7 that ensures that each resource opened in the try block is closed automatically at the end of the block, regardless of whether the try block completes normally or abruptly. Resources must implement the AutoCloseable interface.

Why important: Prevents resource leaks (e.g., open file handles, database connections) and simplifies code by removing the need for explicit finally blocks to close resources.

Use case: Reading from a file, where the BufferedReader (which implements AutoCloseable) is automatically closed.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class TryWithResourcesDemo {
    public static void main(String[] args) {
        String line;
        try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.err.println("Error reading file: " + e.getMessage());
        }
    }
}

49. What is the hashCode() and equals() contract?

Answer: The hashCode() and equals() methods in Object class have a fundamental contract that must be upheld when overriding them, especially when objects are stored in hash-based collections (HashMap, HashSet, Hashtable).

The contract states:

  1. If two objects are equal according to the equals(Object) method, then calling the hashCode() method on each of the two objects must produce the same integer result.
  2. If two objects are not equal according to the equals(Object) method, their hashCode() results are not required to be different (though it's good practice for performance).
  3. If an object's equals() method doesn't change during execution, its hashCode() method must consistently return the same value.

Why important: Failure to adhere to this contract will lead to incorrect behavior in hash-based collections. For example, an object might be added to a HashSet but cannot be found later, or duplicate keys might appear in a HashMap.

Use case: A custom Person class used as keys in a HashMap. Both equals() and hashCode() must be overridden to ensure proper behavior.

import java.util.Objects;

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getters...

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

50. What is Garbage Collection in Java?

Answer: Garbage Collection (GC) is an automatic memory management process in Java that reclaims memory occupied by objects that are no longer referenced by the program. This frees developers from manually deallocating memory, preventing common memory-related bugs like memory leaks and dangling pointers.

Why important: Automates memory management, reduces memory-related errors, and simplifies development.

Use case: After an object's scope ends or all references to it are removed, the GC will eventually mark it for deletion and reclaim its memory.

public class GarbageCollectionDemo {
    public static void main(String[] args) {
        String s1 = new String("Hello");
        String s2 = new String("World");

        s1 = null; // Object "Hello" is now eligible for GC
        s2 = null; // Object "World" is now eligible for GC

        // System.gc(); // Suggests the JVM to run GC, but no guarantee
        System.out.println("Objects made eligible for garbage collection.");
    }
}
0%