Corejava Interview Booster 15
Corejava Interview Booster 15
Spring AOP is a key module of the Spring Framework that allows developers to
implement cross-cutting concerns (like logging, security, transaction management,
etc.) separately from the main business logic. It promotes modularity by allowing
the separation of concerns.
---
1. **Aspect**
- A modular unit of cross-cutting concern.
- Example: Logging, security, or transaction management.
- Declared using `@Aspect` annotation in Spring.
2. **Join Point**
- A specific point during the execution of a program, such as the execution of a
method or the handling of an exception.
- Spring AOP supports method execution join points.
3. **Advice**
- Action taken by an aspect at a particular join point.
- Types of Advice:
- **Before Advice**: Executes before the method.
- **After Advice**: Executes after the method.
- **After Returning Advice**: Executes after the method successfully returns.
- **After Throwing Advice**: Executes if the method throws an exception.
- **Around Advice**: Executes before and after the method.
4. **Pointcut**
- A predicate or expression that matches join points.
- Example: Match all methods in a specific package or class.
5. **Weaving**
- The process of linking aspects with other application types or objects to
create an advised object.
- Spring AOP uses **runtime weaving** (proxies).
---
---
@Aspect
@Component
public class LoggingAspect {
@SpringBootApplication
public class AopExampleApplication {
public static void main(String[] args) {
SpringApplication.run(AopExampleApplication.class, args);
}
}
```
@Service
public class MyService {
public void performTask() {
System.out.println("Executing task...");
}
}
```
#### **Output:**
```
Logging before method execution...
Executing task...
```
---
### **Types of Advice with Example**
---
---
---
---
### Output:
```
Key: 100, Value: dfg
Key: 101, Value: abc
Key: cgh, Value: xxx
```
---
### Explanation:
1. **Heterogeneous Keys and Values**:
- Keys can be of any type, such as `Integer`, `String`, `Double`, etc.
- Values can also be of any type.
- In this case:
- Keys: `100` (Integer), `101` (Integer), `"cgh"` (String)
- Values: `"dfg"`, `"abc"`, `"xxx"` (all Strings)
2. **HashMap Mechanics**:
- The `HashMap` internally uses the `hashCode()` and `equals()` methods of the
key objects to determine where to store and retrieve the key-value pairs.
- As long as the keys implement these methods properly (all Java built-in classes
like `Integer` and `String` do), the `HashMap` can handle them.
3. **No Type Constraints**:
- If the `HashMap` is declared as `HashMap<Object, Object>`, it can store keys
and values of any type.
---
---
2. **Runtime Error**:
- If you try to insert heterogeneous keys, the JVM will throw a
`ClassCastException` because it cannot compare different types.
---
### Example:
#### Case with Homogeneous Keys (Works Fine):
```java
import java.util.TreeMap;
**Output**:
```
Key: 100, Value: A
Key: 150, Value: C
Key: 200, Value: B
```
**Error**:
```
Exception in thread "main" java.lang.ClassCastException: class java.lang.String
cannot be cast to class java.lang.Integer
```
---
**Output**:
```
Key: 100, Value: A
Key: 3.14, Value: C
Key: ABC, Value: B
```
---
2. **Heterogeneous Keys**:
- Use a custom comparator if you want to allow heterogeneous keys, but it is
uncommon and might lead to logical issues.
3. **Practical Recommendation**:
- Stick to homogeneous keys to maintain clear logic and avoid errors.
================================
Your code will **compile successfully**, but it will throw a runtime exception when
executed.
### Explanation:
1. **Raw `TreeMap`**:
- You are using a raw `TreeMap` without specifying a generic type (e.g.,
`TreeMap<Object, String>`).
- This means the keys can be of any type, but the `TreeMap` still requires that
all keys be **mutually comparable** because it sorts them.
2. **Exception at Runtime**:
- When `TreeMap` tries to compare keys (`100` and `"ABC"`) to maintain its order,
it encounters a `ClassCastException` because `Integer` and `String` are not mutually
comparable.
---
This error occurs during the insertion of `"ABC"` because the `TreeMap` internally
uses comparisons to order keys.
---
1. **Homogeneous Keys**:
Always use keys of the same type to avoid such runtime issues.
```java
import java.util.TreeMap;
**Output**:
```
Key: 100, Value: A
Key: 200, Value: B
```
```java
import java.util.TreeMap;
import java.util.Comparator;
treeMap.put(100, "A");
treeMap.put("ABC", "B");
**Output**:
```
Key: 100, Value: A
Key: ABC, Value: B
```
---
// Adding elements
safeList.add("Element1");
safeList.add("Element2");
// Accessing elements (synchronized block is needed for iteration)
synchronized (safeList) {
for (String item : safeList) {
System.out.println(item);
}
}
}
}
```
---
// Adding elements
safeMap.put("Key1", "Value1");
safeMap.put("Key2", "Value2");
// Adding elements
concurrentMap.put("Key1", "Value1");
concurrentMap.put("Key2", "Value2");
---
---
### Recommendations:
- Use `Collections.synchronizedList` for thread-safe `ArrayList`.
- Prefer `ConcurrentHashMap` over `Collections.synchronizedMap` for better
performance and scalability.
===============================
In Java, **fail-safe** and **fail-fast** are terms used to describe how collections
behave when they are being modified during iteration. Here's a detailed explanation:
---
### **Fail-Fast**
#### Example:
```java
import java.util.ArrayList;
import java.util.Iterator;
while (iterator.hasNext()) {
System.out.println(iterator.next());
list.add("C"); // ConcurrentModificationException
}
}
}
```
---
### **Fail-Safe**
#### Example:
```java
import java.util.concurrent.CopyOnWriteArrayList;
---
---
---
1. **`@SpringBootConfiguration`**:
- Marks the class as a configuration class for Spring Boot.
- It is a specialized version of `@Configuration`.
2. **`@EnableAutoConfiguration`**:
- Enables Spring Boot's auto-configuration feature.
- Automatically configures components and libraries based on the dependencies on
the classpath.
3. **`@ComponentScan`**:
- Enables scanning for Spring components (`@Component`, `@Service`,
`@Repository`, `@Controller`, etc.) in the current package and its sub-packages.
---
1. **Simplifies Configuration**:
- Instead of explicitly using `@Configuration`, `@EnableAutoConfiguration`, and
`@ComponentScan`, you can use a single annotation.
3. **Supports Auto-Configuration**:
- Automatically configures beans and settings based on the application's
dependencies.
---
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
```
- **`@SpringBootApplication`**:
- Indicates that this is the main class for a Spring Boot application.
- **`SpringApplication.run()`**:
- Launches the application, starting the embedded web server and initializing the
Spring context.
---
1. **Auto-Configuration**:
- Configures components like databases, web servers, or security based on the
dependencies included in your project.
- For example:
- Adds `DispatcherServlet` if `spring-boot-starter-web` is present.
- Configures `DataSource` if a database driver is on the classpath.
2. **Component Scanning**:
- Automatically detects and registers beans annotated with `@Component`,
`@Service`, etc., within the same package or sub-packages.
---
---
```java
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
```
---
3. **Cleaner Code**:
- Keeps the main class concise and focused.
---
### **Conclusion**
`@SpringBootApplication` is a core annotation in Spring Boot that combines three
important features: configuration (`@Configuration`), auto-configuration
(`@EnableAutoConfiguration`), and component scanning (`@ComponentScan`). It
simplifies the setup and development of Spring Boot applications, making it an
essential part of most Spring Boot projects.
======================
When you use the `@SpringBootApplication` annotation in a Spring Boot project, it
automatically includes `@ComponentScan`. By default, the base package for component
scanning is the **package of the class annotated with `@SpringBootApplication` and
all its sub-packages**.
---
```java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
```
---
2. **Sub-Package Scanning**:
- All sub-packages of the main class's package are included automatically.
3. **No Explicit Configuration Required**:
- For most projects, the default behavior suffices as long as the main class is
in a high-level package.
---
If your components are located in different packages outside the default scanning
path, you can customize the `@ComponentScan` settings.
---
For example:
```
com.example.demo
├── DemoApplication.java (Main class with @SpringBootApplication)
├── services
├── controllers
└── repositories
```
2. **Avoid Hardcoding Scanning Packages**:
- Let Spring Boot's default behavior handle component scanning unless there is a
specific requirement to scan non-standard packages.
---
### **Conclusion**
Each RDBMS (e.g., MySQL, PostgreSQL, Oracle, SQL Server) has its own SQL syntax,
functions, and capabilities. The dialect bridges the differences between these
databases by telling Hibernate how to translate its database-agnostic HQL (Hibernate
Query Language) or JPA Criteria queries into the appropriate native SQL for the
target database.
---
1. **SQL Generation**:
- The dialect specifies the SQL syntax and features for a particular database.
- It ensures that the queries are compatible with the database in use.
2. **Vendor-Specific Features**:
- Manages differences in data types, functions, and keywords.
- Optimizes queries using database-specific features (e.g., pagination syntax).
3. **DDL Generation**:
- Used for creating tables and other schema elements when Hibernate generates
schema (via `hbm2ddl`).
---
---
---
2. **Pagination Support**:
- Dialects define how `LIMIT` and `OFFSET` clauses are handled, which vary
between databases.
4. **Schema Generation**:
- Dialect helps Hibernate in generating correct `CREATE TABLE` statements when
`hibernate.hbm2ddl.auto` is set to `create`.
---
1. **Switching Databases**:
- By changing the dialect and connection URL, you can switch between different
databases without modifying your application code.
2. **Customizing Dialects**:
- If you need to use a custom SQL feature, you can extend a standard dialect and
override methods to include additional behavior.
Example:
```java
public class CustomMySQLDialect extends MySQLDialect {
public CustomMySQLDialect() {
registerFunction("custom_function", new
StandardSQLFunction("custom_function"));
}
}
```
---
### **Conclusion**
### **Code:**
```java
package com.InterviewPrep;
---
---
2. Input: `hello`
```bash
The string "hello" is not a palindrome.
```
======================================
Here’s a detailed comparison of **HashMap** and **Hashtable** in Java:
---
---
- **Hashtable**:
- Synchronized by default.
- Safe for multi-threaded use without additional synchronization.
---
- **Hashtable**:
- Does not allow:
- `null` keys.
- `null` values.
- Example:
```java
Map<String, String> table = new Hashtable<>();
table.put(null, "Value1"); // Throws NullPointerException
table.put("Key1", null); // Throws NullPointerException
```
---
- **Hashtable**:
- Considered legacy.
- Use cases are limited in modern Java programming.
---
- **Hashtable**:
- Uses **fail-safe enumerators** (legacy).
- However, modifications during iteration may not always reflect immediately.
---
- **Hashtable**:
- Useful when legacy code requires a synchronized map and cannot be updated to use
`ConcurrentHashMap`.
---
Here are the **scenarios** where objects and references become eligible for GC:
```java
public class GCExample {
public static void main(String[] args) {
MyClass obj = new MyClass(); // obj references the object
obj = null; // The object is no longer referenced by 'obj'
// obj is eligible for GC
}
}
class MyClass {
// Some properties and methods
}
```
```java
public class GCExample {
public static void main(String[] args) {
method();
}
```java
import java.util.ArrayList;
- **Explanation**: After removing `obj` from the `list`, if there are no other
references to `obj`, it becomes eligible for GC.
```java
public class GCExample {
public static void main(String[] args) {
MyClass a = new MyClass();
MyClass b = new MyClass();
a.setNext(b);
b.setNext(a);
a = null; // Break the external reference
b = null; // Break the external reference
// Now, both objects are unreachable and eligible for GC
}
}
class MyClass {
MyClass next;
void setNext(MyClass next) {
this.next = next;
}
}
```
- **Explanation**: Even though `a` and `b` refer to each other, after both `a`
and `b` are set to `null`, the cycle becomes unreachable and eligible for GC.
```java
import java.lang.ref.WeakReference;
class MyClass {
// Some properties and methods
}
```
- **Explanation**: Once the strong reference (`obj`) is set to `null`, the object
is only weakly referenced and thus eligible for GC.
```java
public class GCExample {
public static void main(String[] args) {
Thread t = new Thread(() -> {
MyClass obj = new MyClass();
// obj is used within the thread
});
t.start();
// Once thread 't' finishes, obj becomes eligible for GC if no other
references exist
}
}
class MyClass {
// Some properties and methods
}
```
```java
public class GCExample {
public static void main(String[] args) {
MyClass obj = new MyClass();
obj = null; // The object is no longer referenced
System.gc(); // Suggests JVM to collect garbage
}
}
class MyClass {
@Override
protected void finalize() {
System.out.println("Finalize method called");
}
}
```
```java
public class GCExample {
public static void main(String[] args) {
new MyClass(); // Anonymous object created
// The anonymous object becomes eligible for GC as soon as it is no
longer referenced
}
}
class MyClass {
// Some properties and methods
}
```
- **Explanation**: The anonymous object has no strong references and becomes
eligible for GC immediately after the statement finishes executing.
---
### Summary:
In general, an object becomes eligible for garbage collection in the following
situations:
- It is no longer referenced by any live thread or active reference.
- It goes out of scope (for example, when a method finishes).
- It is removed from a collection or structure (e.g., list or map).
- Circular references exist but are no longer reachable from any external
references.
- Objects in weak or soft references (like `WeakReference`) become eligible when no
strong references exist.
- An object referenced only by a thread or its finalizer method and with no other
references is eligible once the thread completes.
Garbage collection in Java is performed by the JVM, and objects are not immediately
collected when they become eligible but will be eventually reclaimed when the
garbage collector runs.
======================
Yes, you can say that **lambda expressions** are often used to implement
**functional interfaces** in Java. However, it's important to clarify the
relationship between them:
For example:
```java
@FunctionalInterface
public interface MyFunction {
int apply(int a, int b); // Single abstract method
}
```
For example:
```java
MyFunction add = (a, b) -> a + b;
```
In this example:
- `MyFunction` is a functional interface.
- The lambda expression `(a, b) -> a + b` provides the implementation of the `apply`
method of the `MyFunction` interface.
### Summary:
- **Yes**, lambda expressions are used to provide implementations for **functional
interfaces** in Java.
- A **functional interface** is an interface with just one abstract method, and a
**lambda expression** provides a concise way to implement this method.
==============================
Functional interfaces in Java are interfaces that have exactly one abstract method.
They can have multiple default or static methods, but only one abstract method. Here
are some commonly used **functional interfaces** in Java, along with their examples:
### 1. **`Runnable`**
- **Purpose**: Represents a task that can be executed by a thread. It has a
single method `run()` with no arguments and no return value.
- **Example**:
```java
Runnable runnable = () -> System.out.println("Task is running");
new Thread(runnable).start();
```
### 2. **`Callable<T>`**
- **Purpose**: Similar to `Runnable`, but it allows returning a result or
throwing an exception. It defines a single method `call()` that returns a result of
type `T`.
- **Example**:
```java
Callable<Integer> task = () -> {
return 42;
};
try {
Integer result = task.call();
System.out.println(result); // Output: 42
} catch (Exception e) {
e.printStackTrace();
}
```
### 3. **`Consumer<T>`**
- **Purpose**: Represents an operation that accepts a single input argument and
returns no result. It is used primarily for operations that perform side-effects.
- **Example**:
```java
Consumer<String> printer = (s) -> System.out.println(s);
printer.accept("Hello, World!"); // Output: Hello, World!
```
### 4. **`Supplier<T>`**
- **Purpose**: Represents a supplier of results, i.e., a function that takes no
arguments and returns a result of type `T`.
- **Example**:
```java
Supplier<Integer> randomSupplier = () -> (int) (Math.random() * 100);
System.out.println(randomSupplier.get()); // Output: Random number between 0
and 99
```
### 6. **`Predicate<T>`**
- **Purpose**: Represents a boolean-valued function of one argument. It is used
to test whether a condition holds for the input.
- **Example**:
```java
Predicate<Integer> isEven = (n) -> n % 2 == 0;
System.out.println(isEven.test(4)); // Output: true
System.out.println(isEven.test(5)); // Output: false
```
### 7. **`UnaryOperator<T>`**
- **Purpose**: A special case of `Function` that takes a single argument of type
`T` and returns a result of the same type `T`. It is often used for applying
operations like transformation or modification on an object.
- **Example**:
```java
UnaryOperator<Integer> square = (x) -> x * x;
System.out.println(square.apply(5)); // Output: 25
```
### 8. **`BinaryOperator<T>`**
- **Purpose**: A special case of `BiFunction` that operates on two operands of
the same type `T` and returns a result of the same type `T`.
- **Example**:
```java
BinaryOperator<Integer> add = (a, b) -> a + b;
System.out.println(add.apply(3, 7)); // Output: 10
```
### 12. **`Optional<T>`** (Optional is not strictly a functional interface but used
heavily with functional programming paradigms)
- **Purpose**: Represents a container object which may or may not contain a
value. Used for handling nullable values in a more functional way.
- **Example**:
```java
Optional<String> optional = Optional.of("Hello");
optional.ifPresent(System.out::println); // Output: Hello
```
### Summary:
Functional interfaces are a core part of Java's functional programming features
introduced in Java 8. These interfaces, when combined with **lambda expressions**,
allow for concise and flexible code. Many of these functional interfaces, such as
`Consumer`, `Supplier`, `Function`, and `Predicate`, are part of the
**java.util.function** package and are used extensively in Java Streams and other
functional-style operations.
==========================================
While it's true that a **lambda expression** in Java is an **anonymous method**, it
can still be invoked or used just like any other method, but it is typically
assigned to a **variable** that represents a functional interface. Since the lambda
expression is anonymous (it doesn't have a name), we don't call it directly by name,
but rather by invoking the method of the functional interface it implements.
// Calling the lambda expression via the `test` method of the Predicate interface
System.out.println(isLongString.test("Hello")); // Output: false
System.out.println(isLongString.test("Hello, World!")); // Output: true
```
In this example:
- `Predicate<String>` is a functional interface with the method `test(T t)`.
- The lambda expression `(str) -> str.length() > 5` is assigned to the variable
`isLongString`.
- We call the `test()` method of `isLongString`, which invokes the lambda
expression.
// Calling the lambda expression using the `apply` method of the Function interface
System.out.println(square.apply(5)); // Output: 25
```
In this example:
- `Function<Integer, Integer>` is a functional interface with the method `apply(T
t)`.
- The lambda expression `(x) -> x * x` is assigned to the variable `square`.
- We call the `apply()` method on `square`, which invokes the lambda expression.
### 4. **Using Lambda with Event Handlers (GUI Frameworks like JavaFX, Swing)**
Lambda expressions are also commonly used in event handling, such as with button
clicks in GUI applications.
// Calling the lambda expression when the button is clicked (this would be done by
the framework)
```
In this example:
- The lambda expression `event -> System.out.println("Button clicked!")` is passed
as an event handler.
- The framework (JavaFX) calls the lambda expression when the button is clicked.
In all these cases, **lambda expressions** provide a compact and powerful way to
implement **functional interfaces** and are invoked through the interface methods
that the lambda expression implements.
==================================
Running a Java program as **Javadoc** is not something that you typically do with
the code itself. However, there may be some confusion here between two different
things:
1. **Javadoc Tool**:
- The **Javadoc** tool is a utility provided by Java for generating API
documentation for your Java classes and packages.
- You do not "run" a Java program as Javadoc, but rather you **generate Javadoc**
from the source code.
- Javadoc takes your Java source code and comments (specifically **Javadoc
comments**—multiline comments starting with `/**` and ending with `*/`) and
generates HTML documentation for your classes, methods, fields, and more.
```java
/**
* This is a sample class for demonstrating Javadoc.
*/
public class Sample {
/**
* This method prints a greeting message.
*
* @param name The name of the person to greet.
*/
public void greet(String name) {
System.out.println("Hello, " + name);
}
}
```
For example:
```bash
javadoc -d doc_output Sample.java
```
This command generates the HTML documentation files in the `doc_output` directory.
### Summary
To clarify:
- **Javadoc** is a tool to generate documentation from your Java code.
- **You do not run your Java program as Javadoc**. Instead, you use Javadoc to
generate API documentation from your source code.
- **Javadoc comments** are a special type of comments used to create this
documentation, and these comments help describe what the classes and methods in your
code do.
==================================
In Java, both **`java.util.Date`** and **`java.sql.Date`** are used to represent
dates, but they are intended for different purposes and have distinct behaviors.
Here's a detailed comparison:
### 1. **Package**
- **`java.util.Date`**: This class is part of the `java.util` package.
- **`java.sql.Date`**: This class is part of the `java.sql` package, which is
specifically designed for handling dates in SQL databases.
### 2. **Purpose**
- **`java.util.Date`**: This class is used for representing **both date and
time**. It can represent a specific moment in time (with millisecond precision).
- **`java.sql.Date`**: This class is specifically used for **SQL** database
interactions and represents a **date without time** (year, month, day). It is used
to represent a date in a format that is compatible with SQL `DATE` type, which only
stores the date (no time information).
- **`java.sql.Date`**:
- Primarily intended to be used in JDBC for working with SQL databases.
- It has constructors and methods that allow it to handle SQL `DATE` values.
- It extends `java.util.Date` but overrides some methods to ensure that the
time part is set to `00:00:00.000`.
- Example: `Date sqlDate = new Date(System.currentTimeMillis()); // Represents
today's date without time`
| Feature | `java.util.Date` |
`java.sql.Date` |
|-----------------------------|------------------------------------------|----------
--------------------------------|
| **Package** | `java.util` |
`java.sql` |
| **Purpose** | Represents both date and time |
Represents SQL `DATE` (only year, month, day) |
| **Time Information** | Contains time (hours, minutes, seconds) | No time
information (only year, month, day) |
| **Precision** | Millisecond precision | Only date
(ignores time) |
| **Constructor** | `new Date()` | `new
java.sql.Date(long date)` |
| **Common Use** | General date-time handling | JDBC
(database date handling) |
| **Inherited From** | `Object` | Extends
`java.util.Date` |
### Example:
```java
// java.util.Date (includes time)
java.util.Date utilDate = new java.util.Date(); // Current date and time
System.out.println("java.util.Date: " + utilDate);
// java.sql.Date (only date, no time)
java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis()); // Current
date without time
System.out.println("java.sql.Date: " + sqlDate);
```
**Output**:
```
java.util.Date: Fri Jan 03 15:45:30 IST 2025
java.sql.Date: 2025-01-03
```
### Conclusion:
- **Use `java.util.Date`** for general-purpose date and time handling.
- **Use `java.sql.Date`** when working with SQL databases to handle the `DATE` type
(which doesn’t include time).
================================