Preparing for a Java interview requires a strong understanding of core Java concepts and principles. This comprehensive list covers several important Java interview questions with detailed answers to help you ace your interview:
1. What are the core principles of Object-Oriented Programming (OOP)?
Answer: The four core principles of OOP are:
- Encapsulation: Bundling data (attributes) and the methods that operate on the data into a single unit (class). It also involves hiding the internal implementation details of an object and exposing only a well-defined interface.
- Abstraction: Showing only the essential information to the user and hiding the complex implementation details. It focuses on “what” an object does rather than “how” it does it. Achieved through abstract classes and interfaces.
- Inheritance: A mechanism where a new class (subclass or derived class) inherits properties and behaviors from an existing class (superclass or base class). It promotes code reusability and establishes an “is-a” relationship.
- Polymorphism: The ability of an object to take on many forms. In Java, it’s primarily achieved through method overloading (compile-time polymorphism) and method overriding (runtime polymorphism). It allows you to write more flexible and reusable code.
2. What is the difference between `==` and `.equals()` in Java?
Answer:
- `==` (Equality Operator): Compares the memory addresses (references) of two objects. If two reference variables point to the same object in memory, `==` returns `true`. For primitive data types, it compares the actual values.
- `.equals()` Method: Compares the content or value of two objects. The default implementation of `.equals()` in the `Object` class behaves the same as `==`. However, classes like `String`, `Integer`, and other wrapper classes override the `.equals()` method to provide meaningful content comparison. When comparing objects for equality based on their state, you should override the `.equals()` method in your custom classes. If you override `.equals()`, you should also override `.hashCode()` consistently.
3. What is the difference between an interface and an abstract class in Java?
Answer:
- Interface:
- Can only have abstract methods (until Java 8, which introduced default and static methods).
- Cannot have instance variables (only `static final` constants).
- A class can implement multiple interfaces.
- Represents a contract of what a class can do (“can-do” relationship).
- All methods are implicitly `public abstract` (before Java 8).
- Abstract Class:
- Can have abstract and concrete methods.
- Can have instance variables.
- A class can extend only one abstract class (due to single inheritance in Java for classes).
- Can represent a partial implementation of a class (“is-a” relationship with some implementation provided).
- Abstract methods are declared using the `abstract` keyword and do not have a body. Concrete methods have a body.
When to use which: Use interfaces to define a contract of behavior that multiple unrelated classes can implement. Use abstract classes when you want to provide a common base class with some default implementation and potentially some abstract methods that subclasses must implement.
4. What are the different access modifiers in Java? Explain them.
Answer: Java provides four access modifiers that control the visibility of classes, methods, and variables:
- `public`: Accessible from any class, in any package.
- `protected`: Accessible within the same package and by subclasses in different packages.
- `default` (no modifier): Accessible only within the same package. Also known as package-private.
- `private`: Accessible only within the same class.
5. What is the difference between static and non-static members in Java?
Answer:
- Static Members (belong to the class):
- Declared using the `static` keyword.
- Associated with the class itself, not with any specific instance (object) of the class.
- There is only one copy of a static member shared among all instances of the class.
- Can be accessed directly using the class name (e.g., `ClassName.staticVariable`).
- Static methods can only directly access other static members of the same class.
- Non-Static Members (belong to the object/instance):
- Declared without the `static` keyword.
- Associated with each individual object (instance) of the class.
- Each object has its own copy of non-static members.
- Accessed through an object reference (e.g., `object.instanceVariable`).
- Non-static methods can access both static and non-static members of the same class.
6. What is method overloading and method overriding in Java?
Answer:
- Method Overloading (Compile-time Polymorphism): Defining multiple methods in the same class with the same name but different parameter lists (different number, types, or order of parameters). The compiler determines which method to call based on the arguments passed during the method call.
- Method Overriding (Runtime Polymorphism): A subclass providing a specific implementation for a method that is already defined in its superclass. The method in the subclass must have the same name, parameter list, and return type (or a covariant return type) as the method in the superclass. The method to be executed is determined at runtime based on the actual object type (dynamic method dispatch).
7. What is the Java Garbage Collection? How does it work?
Answer: Java Garbage Collection (GC) is an automatic memory management process that reclaims memory occupied by objects that are no longer in use by the program. It helps prevent memory leaks and makes Java programs more memory-efficient.
How it works (simplified): The JVM’s garbage collector periodically identifies and removes unreferenced objects from the heap memory. Objects are considered unreferenced when there are no active references (variables pointing to them) in the program’s execution paths.
Common GC algorithms involve:
- Mark and Sweep: Identifies live objects (marking) and then reclaims the memory occupied by unmarked objects (sweeping).
- Generational GC: Divides the heap into generations (Young Generation, Old Generation, Permanent Generation/Metaspace) based on the object’s age. Different GC algorithms are applied to different generations based on their characteristics. Most objects are short-lived and reside in the Young Generation, while long-lived objects eventually move to the Old Generation.
The specific GC algorithm used can be configured through JVM options.
8. What is the difference between checked and unchecked exceptions in Java?
Answer:
- Checked Exceptions: Exceptions that the compiler forces you to handle (using a `try-catch` block or declaring them in the method’s `throws` clause). They typically represent exceptional conditions that a well-written application should anticipate and recover from (e.g., `IOException`, `SQLException`).
- Unchecked Exceptions: Exceptions that the compiler does not force you to handle. They typically represent programming errors or runtime conditions that are often difficult or impossible to recover from (e.g., `NullPointerException`, `ArrayIndexOutOfBoundsException`, `IllegalArgumentException`). These are subclasses of `RuntimeException` or `Error`.
9. What is the final keyword in Java? Where can it be used?
Answer: The `final` keyword can be used with variables, methods, and classes:
- `final` variable: Once assigned a value, a `final` variable cannot be reassigned. It acts as a constant.
- `final` method: A `final` method cannot be overridden by subclasses. This is used to prevent subclasses from altering the intended behavior of a method.
- `final` class: A `final` class cannot be subclassed (extended). This is used to create immutable classes or to prevent unintended modification of a class’s behavior. Examples include `String` and `Math` classes.
10. What are the different ways to create threads in Java?
Answer: There are two primary ways to create threads in Java:
- Implementing the `Runnable` interface: Create a class that implements the `Runnable` interface and provides the thread’s execution logic in the `run()` method. Then, create a `Thread` object by passing an instance of your `Runnable` class to its constructor and call the `start()` method on the `Thread` object.
- Extending the `Thread` class: Create a class that extends the `Thread` class and override the `run()` method to provide the thread’s execution logic. Then, create an instance of your `Thread` subclass and call its `start()` method.
Implementing `Runnable` is generally preferred as it allows your class to extend another class if needed (Java doesn’t support multiple inheritance of classes).
11. What is the difference between `sleep()` and `wait()` methods in Java?
Answer: Both `sleep()` and `wait()` can pause the execution of a thread, but they have key differences:
- `sleep()`:
- Is a static method of the `Thread` class.
- Causes the current thread to suspend execution for a specified period.
- The thread *retains* any monitors (locks) it holds while sleeping.
- Does not require a synchronized context.
- When the sleep interval expires, the thread resumes execution.
- Can throw an `InterruptedException` if another thread interrupts the sleeping thread.
- `wait()`:
- Is an instance method of the `Object` class.
- Causes the current thread to release the monitor (lock) it holds on the object and enter the wait set of that object until it is notified by another thread.
- Must be called from within a synchronized block or method that holds the lock on the object on which `wait()` is called.
- The thread remains in the wait set until another thread invokes the `notify()` or `notifyAll()` method on the same object.
- Can also wake up spuriously (without a notification).
- Should always be called in a loop to check the condition after waking up.
- Can throw an `InterruptedException` if the waiting thread is interrupted.
12. What is the purpose of the `synchronized` keyword in Java?
Answer: The `synchronized` keyword in Java is used to control access to shared resources by multiple threads, preventing race conditions and ensuring thread safety. It can be used with:
- Synchronized methods: When a method is declared `synchronized`, only one thread can execute that method on a given object instance at a time. The thread must acquire the lock on the object before entering the method.
- Synchronized blocks: You can synchronize only a specific block of code within a method using `synchronized(objectReference) { … }`. This acquires the lock on the `objectReference` before executing the code within the block.
13. What are Java Collections? List some important Collection classes and interfaces.
Answer: Java Collections Framework is a set of interfaces and classes that provide a way to store and manipulate groups of objects. It provides a unified architecture for representing and working with collections.
Important Interfaces:
- `Collection`: The root interface in the collection hierarchy, representing a group of objects.
- `List`: An ordered collection that can contain duplicate elements (e.g., `ArrayList`, `LinkedList`, `Vector`).
- `Set`: A collection that contains no duplicate elements (e.g., `HashSet`, `LinkedHashSet`, `TreeSet`).
- `Map`: An interface that maps keys to values (e.g., `HashMap`, `LinkedHashMap`, `TreeMap`, `Hashtable`).
- `Queue`: A collection designed for holding elements prior to processing (e.g., `LinkedList`, `PriorityQueue`).
Important Classes (examples):
- `ArrayList`: A resizable array implementation of the `List` interface.
- `LinkedList`: A doubly-linked list implementation of the `List` and `Queue` interfaces.
- `HashSet`: A `Set` implementation backed by a `HashMap`.
- `TreeSet`: A `Set` implementation that keeps its elements sorted.
- `HashMap`: A hash table based implementation of the `Map` interface.
- `TreeMap`: A `Map` implementation that keeps its entries sorted by key.
14. What is the difference between `ArrayList` and `LinkedList` in Java?
Answer:
- `ArrayList`:
- Implements the `List` interface using a dynamic array.
- Provides constant-time (O(1)) access to elements by index.
- Insertion and deletion of elements in the middle can be slow (O(n)) as elements need to be shifted.
- Good for frequent random access (get operations).
- `LinkedList`:
- Implements the `List` and `Queue` interfaces using a doubly-linked list.
- Accessing elements by index takes linear time (O(n)) as you need to traverse the list.
- Insertion and deletion of elements at any position are efficient (O(1)) as only the links need to be updated.
- Good for frequent insertions and deletions.
15. What is the difference between `HashMap` and `Hashtable` in Java?
Answer: Both `HashMap` and `Hashtable` implement the `Map` interface, but they have several key differences:
- Synchronization: `Hashtable` is synchronized, meaning it is thread-safe and can be used by multiple threads without external synchronization. `HashMap` is not synchronized. If you need thread-safe operations with `HashMap`, you can use `Collections.synchronizedMap(new HashMap<>())` or `ConcurrentHashMap`.
- Null Keys and Values: `HashMap` allows one null key and multiple null values. `Hashtable` does not allow null keys or null values; attempting to insert null will result in a `NullPointerException`.
- Performance: Due to synchronization, `Hashtable` is generally slower than `HashMap` in single-threaded environments.
- Iteration: Iterators over `HashMap`’s key set, value set, and entry set are fail-fast, meaning they will throw a `ConcurrentModificationException` if the map is structurally modified while iterating (except through the iterator’s own `remove()` method). Iterators for `Hashtable` are fail-safe (though older and less common now).
In modern Java development, `HashMap` is generally preferred when thread safety is not a requirement. For concurrent scenarios, `ConcurrentHashMap` is a better choice than `Hashtable` due to its finer-grained locking mechanism, which offers better performance.
16. What are Java Generics? What are their benefits?
Answer: Java Generics provide a way to parameterize types. This allows you to create classes, interfaces, and methods that can work with different types while providing compile-time type safety.
Benefits of Generics:
- Type Safety: Generics ensure that you are using the correct type of objects at compile time, reducing the risk of `ClassCastException` at runtime.
- Code Reusability: You can write a single generic class or method that can work with various types without the need for casting or writing separate code for each type.
- Readability: Generic code is often more readable because the type of objects being handled is explicitly specified.
List<String> stringList = new ArrayList<>(); // List that can only hold Strings
stringList.add("Hello");
// stringList.add(123); // Compile-time error
17. What are Lambda Expressions in Java? What are their key features?
Answer: Lambda expressions (introduced in Java 8) provide a concise way to represent anonymous functions. They allow you to pass behavior as data and make code more functional and expressive.
Key Features:
- Anonymous: Lambda expressions don’t have a name.
- Function: They are treated as functions and can be passed around.
- Passed as Argument: Can be passed as arguments to methods or stored in variables.
- Concise: They often require less boilerplate code compared to anonymous inner classes.
Leave a Reply