JAVA8 Interview Questions and Answers
Java 8 Basics Interview Questions
Q1. What are the major features introduced in Java 8?
Answer
Java 8, released in March 2014, is one of the most important releases in Java history. It introduced functional programming capabilities and several powerful APIs that made Java applications more concise, readable, and efficient.
Major Features
- Lambda Expressions
- Stream API
- Functional Interfaces
- Method References
- Default Methods in Interfaces
- Static Methods in Interfaces
- Optional Class
- New Date & Time API (java.time)
- CompletableFuture
- Nashorn JavaScript Engine (deprecated in later Java versions)
Why were these features introduced?
Before Java 8, Java developers had to write verbose code for common operations like sorting, filtering, and processing collections. Java 8 reduced boilerplate code and introduced functional programming concepts to simplify development.
Example
Before Java 8
Collections.sort(employees, new Comparator<Employee>() {
@Override
public int compare(Employee e1, Employee e2) {
return e1.getSalary() – e2.getSalary();
}
});
Java 8
employees.sort((e1, e2) -> e1.getSalary() – e2.getSalary());
Interview Tip
When answering this question, don’t just list the features. Explain why Java 8 introduced them and mention a feature you use in real projects, such as Streams or Lambda Expressions.
Q2. Why is Java 8 considered a revolutionary release?
Answer
Java 8 is considered a revolutionary release because it introduced functional programming into Java while preserving its object-oriented nature. It changed the way developers write Java code by making it shorter, cleaner, and more expressive.
Reasons
- Introduced Lambda Expressions
- Added Stream API for collection processing
- Reduced boilerplate code
- Improved performance with Parallel Streams
- Added a modern Date & Time API
- Introduced Optional to reduce NullPointerException
- Improved interface evolution using Default Methods
Example
Before Java 8
for (Employee emp : employees) {
if (emp.getSalary() > 50000) {
System.out.println(emp.getName());
}
}
Java 8
employees.stream()
.filter(emp -> emp.getSalary() > 50000)
.forEach(emp -> System.out.println(emp.getName()));
Real-Time Usage
In Spring Boot applications, developers commonly use:
- Streams for collection processing
- Lambda Expressions for concise logic
- Optional for null-safe return values
- CompletableFuture for asynchronous tasks
Q3. What problems did Java developers face before Java 8?
Answer
Before Java 8, developers often had to write repetitive and verbose code for tasks that are now much simpler.
Common Problems
- Lengthy anonymous inner classes
- Manual iteration over collections
- No built-in functional programming support
- Difficult parallel processing
- Frequent NullPointerException
- Older Date & Time API (java.util.Date) had design limitations
Example
Before Java 8
List<String> result = new ArrayList<>();
for (String name : names) {
if (name.startsWith(“A”)) {
result.add(name);
}
}
Java 8
List<String> result = names.stream()
.filter(name -> name.startsWith(“A”))
.toList();
Interview Tip
Interviewers may ask:
“Can you explain a real problem that Java 8 solved?”
A good answer is that Java 8 simplified collection processing and significantly reduced boilerplate code.
Q4. What are the advantages of Java 8?
Answer
Java 8 offers several improvements that make enterprise application development easier and more efficient.
Advantages
- Reduced boilerplate code
- Better readability
- Functional programming support
- Simplified collection processing
- Easier parallel programming
- Better null handling using Optional
- Modern Date & Time API
- Improved API evolution with Default Methods
- Better performance for certain data processing tasks
Real-World Example
In a Spring Boot application:
- Streams filter database results.
- Lambda Expressions simplify business logic.
- Optional safely handles nullable values.
- CompletableFuture enables asynchronous service calls.
Q5. What are the limitations of Java before Java 8?
Answer
Before Java 8, Java lacked many modern language features, resulting in more verbose and less expressive code.
Limitations
- No Lambda Expressions
- No Stream API
- No Functional Interfaces
- No Method References
- No Default Methods in Interfaces
- No Optional class
- Legacy Date & Time API with mutable classes
- Limited support for functional programming
- Manual collection processing using loops
Example
Sorting a collection required creating a Comparator implementation, whereas Java 8 allows sorting with a single lambda expression.
Interview Follow-up
A common follow-up question is:
Which Java 8 feature had the biggest impact on enterprise development? A strong answer is Lambda Expressions and Stream API, because they dramatically reduced boilerplate code and made collection processing more readable and maintainable.
Q6. What is Functional Programming?
Answer:
Functional Programming (FP) is a programming paradigm where programs are built by composing functions rather than changing state and mutable data. Java introduced functional programming features in Java 8 while remaining primarily an object-oriented language.
Key Characteristics
- Focuses on functions
- Reduces mutable state
- Encourages declarative programming
- Improves readability and maintainability
Example
List<String> names = List.of(“John”, “Alice”, “Bob”);
names.forEach(name -> System.out.println(name));
Interview Tip
Java supports functional programming but is not a purely functional programming language.
Q7. Is Java a Pure Functional Programming Language?
Answer:
No. Java is primarily an Object-Oriented Programming (OOP) language. Java 8 introduced functional programming features such as Lambda Expressions, Streams, and Functional Interfaces, but Java still supports mutable objects, inheritance, and side effects.
| Pure Functional Languages | Java |
| Haskell | ❌ |
| Clojure | ❌ |
| Scala | Partial |
| Java | OOP + Functional Features |
Interview Tip
A better interview answer is:
Java is an object-oriented language that added functional programming capabilities in Java 8 to simplify coding and improve collection processing.
Q8. What are the new APIs introduced in Java 8?
Answer:
Java 8 introduced several important APIs:
- Stream API – Process collections functionally.
- Date & Time API (java.time) – Modern, immutable date and time classes.
- Optional API – Helps avoid NullPointerException.
- CompletableFuture API – Simplifies asynchronous programming.
Example
employees.stream()
.filter(Employee::isActive)
.forEach(System.out::println);
Interview Tip
The Stream API and Optional are among the most frequently used Java 8 APIs in Spring Boot applications.
Q9. How does Java 8 maintain backward compatibility?
Answer:
Java 8 introduced Default Methods in interfaces, allowing new methods to be added without forcing all existing implementations to change.
Example
interface Vehicle {
void start();
default void stop() {
System.out.println(“Vehicle stopped”);
}
}
Benefits
- Backward compatibility
- Easier API evolution
- Reduced maintenance effort
Interview Tip
Default Methods were introduced to evolve interfaces without breaking existing implementations.
Q10. Which Java 8 features are most commonly used in Spring Boot projects?
Answer:
The most commonly used Java 8 features in Spring Boot applications are:
- Lambda Expressions
- Stream API
- Optional
- Method References
- CompletableFuture
- Date & Time API
Example
Optional<Employee> employee = repository.findById(id);
employee.ifPresent(System.out::println);
Real-Time Usage
These features are widely used for:
- Collection processing
- Database result handling
- Asynchronous service calls
- Null-safe coding
- Cleaner business logic
Interview Tip
When asked which Java 8 features you use, mention the ones you’ve actually used in your projects and explain where you applied them.
Q11. Why do enterprise applications still use Java 8?
Answer:
Java 8 remains one of the most widely used Java versions in enterprise applications because of its stability, long-term support, and compatibility with major frameworks like Spring Boot, Hibernate, and Apache Kafka.
Reasons:
- Stable and mature version
- Large ecosystem support
- Compatible with most enterprise frameworks
- Huge developer community
- Easy migration path to newer Java versions
Real-Time Example
Many banking, insurance, healthcare, and e-commerce applications still run on Java 8 because upgrading large legacy systems requires significant effort and testing.
Interview Tip
If asked why Java 8 is still popular, mention its stability, enterprise adoption, and framework compatibility, not just its features.
Q12. Which Java versions can run Java 8 applications?
Answer:
Java follows the principle of backward compatibility, meaning applications compiled with Java 8 generally run on newer JDK versions without code changes.
Compatibility
| JDK Version | Can Run Java 8 Code? |
| Java 8 | ✅ Yes |
| Java 11 | ✅ Yes |
| Java 17 | ✅ Yes |
| Java 21 | ✅ Yes |
However, if your application depends on deprecated or removed modules, additional changes may be required when upgrading.
Interview Tip
Remember:
- Compile with Java 8 → Run on Java 17/21 → Usually Yes
- Compile with Java 17 → Run on Java 8 → ❌ No
Q13. Which Java 8 features are used most frequently in interviews?
Answer:
Interviewers rarely ask about every Java 8 feature. They usually focus on the most commonly used ones.
Frequently Asked Topics
- Lambda Expressions
- Stream API
- Functional Interfaces
- Method References
- Optional
- Default Methods
- Date & Time API
- CompletableFuture
Common Interview Questions
- Difference between map() and flatMap()
- Difference between forEach() and peek()
- How does Optional prevent NullPointerException?
- What is a Functional Interface?
- Explain Lambda Expressions with an example.
- Difference between Future and CompletableFuture.
Interview Tip
If you’re preparing for 3–8 years of experience, spend extra time on Streams, Optional, CompletableFuture, and Functional Interfaces.
Q14. What are the prerequisites for learning Java 8?
Answer:
Before learning Java 8, you should have a solid understanding of core Java concepts.
Recommended Knowledge
- Classes and Objects
- Inheritance
- Polymorphism
- Interfaces
- Exception Handling
- Collections Framework
- Generics
- Anonymous Inner Classes
Understanding these concepts makes it much easier to learn Lambda Expressions, Streams, and Functional Interfaces.
Example
If you know how to implement a Comparator using an anonymous inner class, you’ll quickly understand how Lambda Expressions simplify the same code.
Interview Tip
Many Java 8 interview questions combine Collections + Streams, so revise the Collections Framework before diving deep into Streams.
Q15. What is the difference between Java 7 and Java 8?
Answer:
Java 8 introduced several new language features and APIs that significantly improved developer productivity compared to Java 7.
| Feature | Java 7 | Java 8 |
| Lambda Expressions | ❌ | ✅ |
| Stream API | ❌ | ✅ |
| Functional Interfaces | ❌ | ✅ |
| Method References | ❌ | ✅ |
| Optional Class | ❌ | ✅ |
| Default Methods | ❌ | ✅ |
| Date & Time API | Legacy (java.util.Date) | Modern (java.time) |
| CompletableFuture | ❌ | ✅ |
Example
Java 7
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
Java 8
names.sort(String::compareTo);
Interview Tip
Don’t simply list the new features. Explain how they improved Java development, such as reducing boilerplate code, enabling functional programming, and simplifying collection processing.
Q16. What is the difference between Imperative Programming and Declarative Programming?
Answer:
Imperative Programming focuses on how to perform a task by writing step-by-step instructions.
Declarative Programming focuses on what needs to be achieved without explicitly describing every step.
Java 8 introduced Streams, which encourage a more declarative programming style.
Example
Imperative Style (Before Java 8)
List<String> result = new ArrayList<>();
for (String name : names) {
if (name.startsWith(“A”)) {
result.add(name);
}
}
Declarative Style (Java 8)
List<String> result = names.stream()
.filter(name -> name.startsWith(“A”))
.toList();
Comparison
| Imperative | Declarative |
| Focuses on how | Focuses on what |
| More boilerplate code | Less code |
| Manual iteration | Stream API handles iteration |
| Harder to read | More readable |
Interview Tip
A common interview question is:
Why is the Stream API considered declarative?
Because you specify what operation should be performed (filter, map, sort) instead of manually iterating over the collection.
Q17. How did Java 8 improve code readability and maintainability?
Answer:
Java 8 introduced features that significantly reduced boilerplate code and made programs easier to understand and maintain.
Major Improvements
- Lambda Expressions reduce anonymous inner classes.
- Stream API simplifies collection processing.
- Method References make code cleaner.
- Optional reduces null-checking code.
- Default Methods allow interface evolution without breaking existing implementations.
Example
Before Java 8
for (Employee emp : employees) {
System.out.println(emp.getName());
}
Java 8
employees.forEach(Employee::getName);
Note: The above line only invokes the method reference. To print employee names, use:
employees.stream()
.map(Employee::getName)
.forEach(System.out::println);
Benefits
- Easier to read
- Less repetitive code
- Easier maintenance
- Better collaboration in large projects
Interview Tip
Don’t say Java 8 only reduced code. Explain that it also improved maintainability and expressiveness.
Q18. What are the limitations of Java 8?
Answer:
Although Java 8 introduced many powerful features, it also has some limitations.
Limitations
- Stream API is not suitable for every use case.
- Overusing Streams can make code difficult to debug.
- Parallel Streams may reduce performance for small datasets.
- Lambda Expressions can reduce readability if overused.
- Optional should not be used for entity fields or method parameters.
- Java 8 lacks features introduced in later versions, such as Records, Switch Expressions, Text Blocks, and Virtual Threads.
Example
Avoid writing overly complex Stream pipelines like:
employees.stream()
.filter(…)
.map(…)
.flatMap(…)
.sorted(…)
.collect(…);
If the pipeline becomes difficult to understand, consider breaking it into smaller steps.
Interview Tip
Interviewers appreciate balanced answers. Mention both the strengths and the limitations of Java 8.
Q19. What are the best practices when using Java 8 features?
Answer:
Following best practices helps improve code quality and maintainability.
Best Practices
- Use Streams for collection processing, not for every loop.
- Prefer Method References when they improve readability.
- Keep Lambda Expressions short and simple.
- Use Optional only for return types where appropriate.
- Avoid modifying shared mutable data in Parallel Streams.
- Write meaningful method names when using functional interfaces.
- Break complex Stream operations into smaller steps.
Good Example
List<String> activeEmployees = employees.stream()
.filter(Employee::isActive)
.map(Employee::getName)
.toList();
Avoid
- Deeply nested Streams
- Long Lambda Expressions
- Unnecessary use of Parallel Streams
Interview Tip
Good Java developers know when not to use Streams or Lambdas.
Q20. Which Java 8 features should every Java developer master?
Answer:
Every Java developer should have a strong understanding of the most commonly used Java 8 features.
Must-Know Topics
- Lambda Expressions
- Functional Interfaces
- Method References
- Stream API
- Collectors
- Optional
- Default Methods
- Date & Time API
- CompletableFuture
- Parallel Streams
Priority for Interviews
⭐⭐⭐⭐⭐ Very Important
- Lambda Expressions
- Stream API
- Functional Interfaces
- Optional
⭐⭐⭐⭐ Important
- Method References
- Collectors
- CompletableFuture
⭐⭐⭐ Good to Know
- Date & Time API
- Parallel Streams
- Default Methods
Interview Tip
For 3+ years of experience, interviewers usually expect practical knowledge of Streams, Optional, and CompletableFuture rather than just definitions. Be prepared to explain where you’ve used them in real projects.
Category2: Lambda Expressions
Q21. What is a Lambda Expression?
Answer:
A Lambda Expression is an anonymous function introduced in Java 8 that allows you to implement a functional interface using a concise syntax.
Instead of creating an anonymous inner class, you can write the implementation in a single expression or code block.
Syntax
(parameters) -> expression
or
(parameters) -> {
// statements
}
Example
Runnable runnable = () -> System.out.println(“Hello Java 8”);
runnable.run();
Advantages
- Less boilerplate code
- Improved readability
- Easier implementation of Functional Interfaces
- Works seamlessly with Stream API
Interview Tip
A Lambda Expression does not create a new anonymous class. It provides an implementation for the single abstract method of a Functional Interface.
Q22. Why were Lambda Expressions introduced?
Answer:
Lambda Expressions were introduced to simplify Java code and bring functional programming capabilities to the language.
Before Java 8, developers had to write verbose anonymous inner classes even for simple tasks.
Before Java 8
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
};
Java 8
Comparator<String> comparator =
(s1, s2) -> s1.compareTo(s2);
Benefits
- Reduces boilerplate code
- Improves readability
- Simplifies event handling
- Makes collection processing easier
- Enables functional programming
Interview Tip
Don’t answer:
“Lambda Expressions reduce code.”
Instead say:
“Lambda Expressions reduce boilerplate code and enable functional programming by allowing concise implementations of Functional Interfaces.”
Q23. What is the syntax of a Lambda Expression?
Answer:
The basic syntax is:
(parameters) -> expression
or
(parameters) -> {
// multiple statements
}
Syntax Components
- Parameters – Input values.
- Arrow (->) – Separates parameters from the body.
- Body – Contains the implementation.
Examples
No Parameters
() -> System.out.println(“Hello”);
One Parameter
name -> System.out.println(name);
Multiple Parameters
(a, b) -> a + b;
Multiple Statements
(a, b) -> {
int sum = a + b;
return sum;
};
Interview Tip
If there is only one parameter, parentheses are optional.
Example:
name -> System.out.println(name);
Q24. What are the components of a Lambda Expression?
Answer:
A Lambda Expression consists of three main components.
1. Parameters
Input values passed to the lambda.
(a, b)
2. Arrow Operator (->)
Separates parameters from the implementation.
->
3. Body
Contains the logic to execute.
(a, b) -> a + b
or
(a, b) -> {
return a + b;
}
Complete Example
BiFunction<Integer, Integer, Integer> add =
(a, b) -> a + b;
Interview Tip
Many interviewers ask:
Explain every part of a Lambda Expression.
Always mention:
- Parameters
- Arrow Operator
- Body
Q25. What are the different ways to write Lambda Expressions?
Answer:
Lambda Expressions can be written in several forms depending on the number of parameters and statements.
1. No Parameters
() -> System.out.println(“Welcome”);
2. Single Parameter
name -> System.out.println(name);
3. Multiple Parameters
(a, b) -> a + b;
4. Multiple Statements
(a, b) -> {
int sum = a + b;
return sum;
};
5. Returning an Object
id -> new Employee(id);
6. Using Method References (Alternative)
employees.forEach(System.out::println);
Although this is a Method Reference, interviewers often ask when it can replace a Lambda Expression.
Interview Tip
Choose the simplest form that keeps the code readable. If the lambda only calls an existing method, consider using a Method Reference instead.
Q26. Can a Lambda Expression have no parameters?
Answer:
Yes. A Lambda Expression can have zero parameters when the functional interface’s abstract method does not accept any arguments.
The syntax for a lambda with no parameters uses empty parentheses ().
Syntax
() -> {
// implementation
}
Example
Runnable runnable = () -> System.out.println(“Executing task”);
runnable.run();
Output
Executing task
In this example, the run() method of the Runnable interface does not take any parameters, so the lambda expression uses empty parentheses.
Real-Time Usage
- Implementing Runnable
- Scheduling background tasks
- Event handling
- Executing asynchronous operations
Interview Tip
If the abstract method has no parameters, you must use empty parentheses ().
Q27. Can a Lambda Expression have one parameter?
Answer:
Yes. A Lambda Expression can have a single parameter.
When there is only one parameter and its type can be inferred, the parentheses are optional.
Example 1 (Without Parentheses)
name -> System.out.println(name);
Example 2 (With Parentheses)
(name) -> System.out.println(name);
Both examples are valid.
Example using Consumer
Consumer<String> consumer = name -> System.out.println(name);
consumer.accept(“JavaToVictory”);
Output
JavaToVictory
Interview Tip
Although parentheses are optional for a single parameter, many teams prefer using them consistently for better readability.
Q28. Can a Lambda Expression have multiple parameters?
Answer:
Yes. A Lambda Expression can have two or more parameters.
When multiple parameters are present, parentheses are mandatory.
Syntax
(parameter1, parameter2) -> expression
Example
BiFunction<Integer, Integer, Integer> add =
(a, b) -> a + b;
System.out.println(add.apply(10, 20));
Output
30
Another Example
Comparator<String> comparator =
(s1, s2) -> s1.compareTo(s2);
Here, the lambda accepts two parameters and compares two strings.
Interview Tip
For multiple parameters, parentheses cannot be omitted.
✔ Correct
(a, b) -> a + b
❌ Incorrect
a, b -> a + b
Q29. Can a Lambda Expression return a value?
Answer:
Yes. A Lambda Expression can return a value.
If the lambda body contains a single expression, Java returns the result automatically.
Example
BinaryOperator<Integer> multiply =
(a, b) -> a * b;
System.out.println(multiply.apply(5, 6));
Output
30
Using return Statement
If the lambda body contains multiple statements, you must explicitly use the return keyword.
BinaryOperator<Integer> add = (a, b) -> {
int result = a + b;
return result;
};
Interview Tip
- Single expression → return is not required.
- Multiple statements → return is mandatory.
Q30. Can a Lambda Expression contain multiple statements?
Answer:
Yes. A Lambda Expression can contain multiple statements.
When the body has more than one statement, it must be enclosed within curly braces {}.
Example
BinaryOperator<Integer> calculator = (a, b) -> {
System.out.println(“Calculating sum…”);
int sum = a + b;
return sum;
};
Output
Calculating sum…
30
Rules
- Use {} for multiple statements.
- Use return if the method returns a value.
- Multiple local variables can be declared inside the lambda body.
Real-Time Example
employees.forEach(employee -> {
System.out.println(employee.getName());
auditService.log(employee.getId());
});
Here, the lambda performs multiple operations for each employee.
Interview Tip
Keep Lambda Expressions short. If the logic becomes complex or spans many lines, move it to a separate method and use a Method Reference or call that method from the lambda. This improves readability and maintainability.
Q31. What is the difference between a Lambda Expression and an Anonymous Inner Class?
Answer:
Both Lambda Expressions and Anonymous Inner Classes are used to provide implementations of interfaces without creating a separate class. However, Lambda Expressions are more concise and efficient.
Comparison
| Feature | Lambda Expression | Anonymous Inner Class |
| Syntax | Short and concise | Verbose |
| Code Readability | High | Low |
| Creates a Separate Class | No | Yes |
| this Keyword | Refers to enclosing class | Refers to anonymous class |
| Suitable For | Functional Interfaces | Any interface or abstract class |
Anonymous Inner Class
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(“Running…”);
}
};
Lambda Expression
Runnable runnable = () -> System.out.println(“Running…”);
Interview Tip
If an interface has only one abstract method, always prefer a Lambda Expression for cleaner and more readable code.
Q32. What are the advantages of Lambda Expressions?
Answer:
Lambda Expressions make Java code simpler, cleaner, and easier to maintain.
Advantages
- Reduces boilerplate code
- Improves code readability
- Enables Functional Programming
- Works seamlessly with Stream API
- Simplifies Collection processing
- Encourages reusable code
- Easier to write event-handling logic
- Better support for parallel processing
Example
Without Lambda
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
With Lambda
Collections.sort(names, (s1, s2) -> s1.compareTo(s2));
Real-Time Usage
Lambda Expressions are commonly used in:
- Stream API
- Collection sorting
- Filtering data
- Spring Boot applications
- Event listeners
- CompletableFuture
Interview Tip
Instead of saying “Lambda reduces code,” explain how it reduces boilerplate code and improves readability.
Q33. What are the limitations of Lambda Expressions?
Answer:
Although Lambda Expressions provide many benefits, they also have some limitations.
Limitations
- Can implement only Functional Interfaces.
- Cannot extend abstract classes.
- Not suitable for complex business logic.
- Debugging can be more difficult.
- Excessive use may reduce code readability.
- Cannot declare instance variables inside a lambda.
- Local variables accessed inside a lambda must be effectively final.
Example
Avoid writing long Lambda Expressions like this:
employees.stream()
.filter(emp -> {
// 30-40 lines of code
return true;
});
Instead, move complex logic into a separate method.
employees.stream()
.filter(this::isEligibleEmployee);
Best Practice
Keep Lambda Expressions small, simple, and focused on a single task.
Interview Tip
If your lambda exceeds 5–10 lines, consider extracting the logic into a separate method.
Q34. What is an Effectively Final Variable?
Answer:
An Effectively Final Variable is a local variable whose value is assigned only once and is never modified afterward.
Such variables can be accessed inside Lambda Expressions without explicitly declaring them as final.
Example
int bonus = 1000;
employees.forEach(emp ->
System.out.println(emp.getSalary() + bonus));
Here, bonus is effectively final because its value is never changed.
Invalid Example
int bonus = 1000;
bonus++;
employees.forEach(emp ->
System.out.println(emp.getSalary() + bonus));
This results in a compilation error because bonus is no longer effectively final.
Why this restriction?
Local variables live on the stack, while Lambda Expressions may execute later. Restricting access to effectively final variables avoids inconsistent behavior and simplifies implementation.
Interview Tip
A favorite interview question is:
Is every effectively final variable declared using the final keyword?
Answer:
No. It behaves like a final variable even if the final keyword is omitted, as long as the value is never reassigned.
Q35. Can a Lambda Expression access local variables?
Answer:
Yes. A Lambda Expression can access:
- Local variables (if they are effectively final)
- Instance variables
- Static variables
Example 1 – Local Variable
int tax = 10;
Function<Integer, Integer> calculate =
salary -> salary + tax;
System.out.println(calculate.apply(50000));
Here, tax is effectively final.
Example 2 – Instance Variable
public class EmployeeService {
private int bonus = 5000;
public void printBonus() {
employees.forEach(emp ->
System.out.println(emp.getSalary() + bonus));
}
}
Instance variables can be modified and accessed inside Lambda Expressions.
Example 3 – Static Variable
private static String company = “JavaToVictory”;
employees.forEach(emp ->
System.out.println(company));
Static variables are also accessible.
Summary
| Variable Type | Accessible in Lambda? |
| Local Variable | ✅ Yes (Effectively Final) |
| Instance Variable | ✅ Yes |
| Static Variable | ✅ Yes |
Interview Tip
A common interview question is:
Why can instance variables be modified inside a Lambda, but local variables cannot?
Answer: Instance and static variables are stored in the heap and have a longer lifetime, whereas local variables are stored on the stack and disappear when the method completes. Restricting local variables to being effectively final avoids issues related to variable lifetime and consistency.
Q36. Can Lambda Expressions call default and static methods of interfaces?
Answer
Yes.
A Lambda Expression can invoke both default and static methods defined in a Functional Interface. However, the Lambda itself provides the implementation only for the single abstract method.
Example
@FunctionalInterface
interface Calculator {
int add(int a, int b);
default void print() {
System.out.println(“Default Method”);
}
static void display() {
System.out.println(“Static Method”);
}
}
Calculator cal = (a, b) -> a + b;
System.out.println(cal.add(10, 20));
cal.print();
Calculator.display();
Output
30
Default Method
Static Method
Interview Tip
Remember that a Lambda Expression implements only the abstract method. Default and static methods already have implementations in the interface.
Q37. Can Lambda Expressions throw checked exceptions?
Answer
Yes, but only if the Functional Interface’s abstract method declares the checked exception.
Valid Example
@FunctionalInterface
interface FileProcessor {
void process() throws IOException;
}
FileProcessor fp = () -> {
throw new IOException(“File not found”);
};
Invalid Example
Runnable runnable = () -> {
throw new IOException(“Error”);
};
The above code will not compile because Runnable.run() does not declare throws IOException.
Interview Tip
A Lambda cannot throw a checked exception unless the Functional Interface’s abstract method declares it.
Q38. What is Variable Capture in Lambda Expressions?
Answer
Variable Capture refers to the ability of a Lambda Expression to access variables from its enclosing scope.
A Lambda can capture:
- Local variables (must be effectively final)
- Instance variables
- Static variables
Example
int bonus = 1000;
Function<Integer, Integer> calculateSalary =
salary -> salary + bonus;
System.out.println(calculateSalary.apply(50000));
Here, bonus is captured by the Lambda Expression.
Interview Tip
A common follow-up question is:
Why must captured local variables be effectively final?
The answer is that local variables are stored on the stack, while a Lambda may execute later. Making them effectively final avoids inconsistent behavior.
Q39. How are Lambda Expressions used with Collections?
Answer
Lambda Expressions simplify common Collection operations such as iteration, sorting, filtering, and searching.
Printing Collection Elements
List<String> names = Arrays.asList(“John”, “Alice”, “Bob”);
names.forEach(name -> System.out.println(name));
Sorting
employees.sort((e1, e2) ->
e1.getSalary().compareTo(e2.getSalary()));
Filtering
employees.stream()
.filter(emp -> emp.getSalary() > 50000)
.forEach(System.out::println);
Interview Tip
In real-world applications, Lambda Expressions are most commonly used together with the Stream API rather than independently.
Q40. What are the best practices for writing Lambda Expressions?
Answer
Following best practices helps improve code readability and maintainability.
Best Practices
- Keep Lambda Expressions short and readable.
- Avoid writing complex business logic inside a Lambda.
- Use Method References (::) whenever they improve readability.
- Use meaningful parameter names.
- Avoid deeply nested Lambdas.
- Prefer Streams for collection processing.
- Extract lengthy logic into separate methods.
Bad Example
employees.stream()
.filter(emp -> {
// 20+ lines of business logic
return true;
});
Better Approach
employees.stream()
.filter(this::isEligibleEmployee);
Interview Tip
A good Lambda should perform one clear task. If it becomes lengthy or difficult to understand, move the logic into a separate method.
Category3: Functional Interfaces
Q41. What is a Functional Interface?
Answer
A Functional Interface is an interface that contains exactly one abstract method. It can have multiple default, static, and private (Java 9+) methods.
Lambda Expressions work only with Functional Interfaces.
Example
@FunctionalInterface
interface Calculator {
int add(int a, int b);
}
The above interface is a Functional Interface because it contains only one abstract method.
Example using Lambda
Calculator calculator = (a, b) -> a + b;
System.out.println(calculator.add(10, 20));
Output
30
Interview Tip
A Functional Interface may contain multiple default and static methods. The only restriction is that it must have exactly one abstract method.
Q42. Why were Functional Interfaces introduced in Java 8?
Answer
Functional Interfaces were introduced to support Lambda Expressions and enable Functional Programming in Java.
Before Java 8, developers had to use Anonymous Inner Classes, which required more boilerplate code.
Before Java 8
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(“Running…”);
}
};
Java 8
Runnable runnable = () -> System.out.println(“Running…”);
Advantages
- Reduces boilerplate code
- Improves readability
- Supports Lambda Expressions
- Enables Stream API
- Encourages Functional Programming
Interview Tip
If asked, “Why can’t Lambda Expressions work without Functional Interfaces?”
Answer:
Because the compiler needs a single abstract method to determine which method the Lambda Expression is implementing.
Q43. What is the @FunctionalInterface annotation?
Answer
@FunctionalInterface is a marker annotation introduced in Java 8.
It tells the compiler that the interface is intended to be a Functional Interface.
If more than one abstract method is declared, the compiler throws an error.
Valid Example
@FunctionalInterface
interface Printer {
void print();
}
Invalid Example
@FunctionalInterface
interface Calculator {
void add();
void subtract();
}
Compilation Error
Unexpected @FunctionalInterface annotation.
Calculator is not a functional interface.
Interview Tip
The annotation is optional, but using it is considered a best practice because it helps the compiler detect accidental changes.
Q44. Is the @FunctionalInterface annotation mandatory?
Answer
No.
The annotation is optional.
An interface is considered a Functional Interface as long as it has only one abstract method, even if the annotation is not present.
Example
interface Greeting {
void sayHello();
}
This is still a Functional Interface.
Adding the annotation only provides compile-time validation.
@FunctionalInterface
interface Greeting {
void sayHello();
}
Both interfaces work the same way.
Interview Tip
Many candidates incorrectly believe that the annotation is mandatory. It is not.
Q45. Can a Functional Interface have multiple default and static methods?
Answer
Yes.
A Functional Interface can contain any number of default and static methods because they already have implementations.
Only the number of abstract methods is restricted.
Example
@FunctionalInterface
interface Calculator {
int add(int a, int b);
default void print() {
System.out.println(“Default Method”);
}
static void display() {
System.out.println(“Static Method”);
}
}
This is still a valid Functional Interface because there is only one abstract method.
Interview Tip
Interviewers often ask:
How many default methods can a Functional Interface have?
Answer:
There is no limit. It can have multiple default and static methods, but only one abstract method.
