Java Interview Notes With Answers
Java Interview Notes With Answers
Spring’s Dependency Injection is a cornerstone feature that supports Inversion of Control (IoC). It allows the framework to handle the instantiation and life-cycle of objects, thereby inverting the control flow compared to traditional production patterns. Dependency Injection separates the creation of object dependencies from business logic, leading to loosely coupled code and easier unit testing. IoC is achieved by enabling objects to acquire their dependencies at runtime rather than compile-time setup, which fosters more flexible and reusable components .
The Servlet lifecycle facilitates web application development by providing a structured approach to request processing and resource management. It comprises three key methods: init(), service(), and destroy(). The init() method initializes the servlet and is executed once when the servlet is loaded. The service() method processes client requests and is invoked for each request, allowing the servlet to read data from the client's request and create responses accordingly. The destroy() method is called once the servlet is being taken out of service, allowing for cleanup of resources. This lifecycle ensures efficient handling of requests, session management, and resource allocation, which are essential for robust web application solutions .
Encapsulation in Object-Oriented Programming works by restricting direct access to some of an object's components and can be achieved using access modifiers. It involves wrapping the data (variables) and the code acting on the data (methods) together as a single unit. The data is not accessible directly; one must use getter and setter methods. The benefits include enhanced security of data by hiding it from outside interference and misuse, improved modularity by hiding the complexity of an object's operations from other classes, and flexibility and maintainability of code .
Within the Java Virtual Machine (JVM), the garbage collector functions to automatically remove objects that are no longer in use to free up resources; this is crucial for long-running applications. It primarily operates in the heap memory, where it identifies and discards unreachable objects, i.e., objects that cannot be accessed in any possible scenario. This process helps in managing memory efficiently by reclaiming memory consumed by abandoned objects and thereby preventing memory leaks .
Java's HashMap manages collisions using a combination of arrays, linked lists, and a red-black tree. Initially, the HashMap uses an array of linked lists where each bucket in the array corresponds to a hash code. When a collision occurs (multiple keys hash to the same bucket), these entries are stored in a linked list at that bucket. Starting with Java 8, if the number of entries in a bucket exceeds a certain threshold (default is 8), that linked list is transformed into a red-black tree, which provides faster search times, ensuring O(log n) performance compared to O(n) in linked lists for large buckets .
Java's abstract classes differ from interfaces primarily in their flexibility and usage. An abstract class can contain both complete and incomplete members (i.e., methods with or without a body), whereas an interface can typically only contain method signatures (Java 8 and onwards allow default and static methods). Abstract classes can maintain state via instance variables, while interfaces cannot. This affects multiple inheritance because interfaces allow a form of it as a class can implement multiple interfaces, whereas a class can only extend one abstract class - adhering to single inheritance. This distinction impacts design decisions when a class needs to inherit behavior from multiple sources .
The Stream API in Java 8 enhances data processing by providing a high-level abstraction for operations on collections of objects. It allows developers to write concise, efficient, and parallelizable code to perform bulk operations on data sets, such as filtering, mapping, and reducing. Streams facilitate a functional programming approach, enabling developers to focus on the 'what' instead of the 'how' by abstracting away the process of iteration. This leads to more readable and maintainable code. Additionally, the Stream API can handle lazy computation, where operations are evaluated only as needed, optimizing performance .
The difference between 'implements Runnable' and 'extends Thread' pertains to class hierarchy and scalability. 'implements Runnable' allows a class to extend another class because it does not require the class to be a child of Thread, so it can maintain a flexible class hierarchy. This approach is preferred for large projects as it decouples the task from the execution mechanism, making it more scalable and manageable . 'extends Thread', on the other hand, should be used when you want to override specific methods of the Thread class as it creates a subclass of Thread, tightly coupling the task with Thread, which is less flexible in inheritance scenarios .
Hibernate implements object-relational mapping (ORM) by mapping Java classes to database tables and Java data types to SQL data types, allowing for seamless data manipulation and retrieval using object-centric logic. Annotations such as @Entity and @Id play crucial roles. @Entity marks a class that should be persisted to a database, and @Id defines the primary key of the entity, essential for identifying specific records. These annotations simplify configuration and help in maintaining cleaner, more maintainable code, leveraging Hibernate’s capabilities of transparent caching, lazy loading, and optimized performance through intelligent fetching strategies .
A Checked Exception in Java is one that is checked at compile time, which means the programmer must handle these exceptions to make the program compile. They often indicate recoverable conditions and examples include SQLException and IOException . In contrast, an Unchecked Exception is not checked at compile time. These are typically runtime exceptions such as ArithmeticException and NullPointerException that usually signify programming defects such as logic errors or improper use of an API .