Explore a comprehensive collection of Java interview questions and answers tailored for Infosys, a leading global consulting and information technology services company. These curated interview questions cover a wide range of Java topics, from core concepts to advanced topics, providing aspiring candidates with a valuable resource to prepare for their Infosys Java interviews.
Q1. How to submit exceptions from child to parent in Java?
Ans: In Java, exceptions are not directly "submitted" or transferred from a child class to a parent class. However, you can achieve a similar effect by allowing the exception to propagate up the call stack until it reaches a suitable exception handler. This typically involves catching the exception in the child class and then rethrowing it or allowing it to propagate up to a higher level.
Here's a simple example:
class Parent {
void performOperation() {
try {
// Your code that may throw an exception
// For example, simulate an exception
throw new RuntimeException("Exception in Parent class");
} catch (RuntimeException e) {
handleException(e);
}
}
void handleException(RuntimeException e) {
// Handle the exception in the parent class
System.out.println("Exception handled in Parent class: " + e.getMessage());
}
}
class Child extends Parent {
@Override
void performOperation() {
try {
// Your code in the child class
super.performOperation(); // Call the parent's method
} catch (RuntimeException e) {
// Catch the exception thrown by the parent
// Do any specific handling if needed
System.out.println("Exception caught in Child class: " + e.getMessage());
// Optionally, rethrow the exception to allow it to propagate further
throw e;
}
}
}
public class Main {
public static void main(String[] args) {
Child child = new Child();
child.performOperation();
}
}
In this example, the Child class overrides the performOperation method from the Parent class. When an exception occurs in the parent class, it catches the exception, calls handleException to handle it, and then continues execution.
The Child class can catch the exception thrown by the parent class, perform additional handling if necessary, and then rethrow the exception or let it propagate further up the call stack.
Remember that this approach works for checked exceptions as well. Ensure that the exception types match or are compatible between the parent and child classes.
Q2. What is an Optional class in Java?
Ans: The Optional class in Java is a container class that may or may not contain a non-null value. It was introduced in Java 8 as part of the java.util package to help alleviate the problem of dealing with null values and NullPointerExceptions. The primary goal of Optional is to provide a more expressive way to represent and handle the absence of a value.
Here are some key points about the Optional class:
1. Avoiding Null:
- Optional is designed to encourage the avoidance of null references. Instead of returning a null to signify the absence of a value, a method can return an Optional instance.
2. Creation of Optional:
- You can create an Optional instance using static factory methods like of, ofNullable, and empty.
- Optional.of(value): Creates an Optional containing the specified non-null value.
- Optional.ofNullable(value): Creates an Optional containing the specified value, or an empty Optional if the value is null.
- Optional.empty(): Creates an empty Optional.
3. Accessing the Value:
- You can use methods like get, orElse, orElseGet, and orElseThrow to access the value inside the Optional or provide a default value or action if the value is absent.
4. Avoiding NullPointerExceptions:
- Using Optional helps in writing more expressive and concise code that avoids accidental NullPointerExceptions caused by attempting to access methods or fields on null references.
5. Chaining Methods:
- Optional provides methods like map, flatMap, and filter that allow you to chain operations on the value inside the Optional in a more functional programming style.
Here's a simple example:
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
// Creating Optional instances
Optional<String> nonEmptyOptional = Optional.of("Hello, Optional!");
Optional<String> emptyOptional = Optional.empty();
// Accessing the value
String value = nonEmptyOptional.get();
System.out.println("Value: " + value);
// Using orElse to provide a default value
String defaultValue = emptyOptional.orElse("Default Value");
System.out.println("Default Value: " + defaultValue);
// Using map to transform the value
nonEmptyOptional.map(String::toUpperCase).ifPresent(result ->
System.out.println("Transformed Value: " + result)
);
}
}
It's important to use Optional judiciously and not overuse it. It's generally recommended for method return types and not as a replacement for all uses of null. Additionally, be cautious when using get() without checking if a value is present, as it can lead to a NoSuchElementException.
Q3. Difference between @RestController and @Controller.
Ans: In Spring Framework, @Controller and @RestController are annotations used to define classes as controllers, but they serve different purposes and are used in different contexts.
1. @Controller:
- @Controller is a traditional Spring MVC controller annotation used to define a class as a controller. It is typically used for creating web applications following the Model-View-Controller (MVC) architectural pattern.
- Controllers annotated with @Controller are capable of handling HTTP requests and returning views. They often have methods annotated with @RequestMapping to map specific URLs to controller methods.
- The methods in a @Controller class return a view name or a ModelAndView object, and the view resolution is handled by the Spring MVC view resolver.
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class MyController {
@RequestMapping("/hello")
public String hello() {
return "helloPage";
}
}
2. @RestController:
- @RestController is a specialized version of @Controller introduced in Spring 4.0. It is specifically designed for building RESTful web services. The @RestController annotation combines the @Controller and @ResponseBody annotations.
- Controllers annotated with @RestController return the data directly as the HTTP response body. The response is often serialized to JSON or XML, and there is no view resolution involved. Each method in a @RestController class is annotated with @RequestMapping or other request mapping annotations.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class MyRestController {
@GetMapping("/hello")
public String hello() {
return "Hello, REST!";
}
}
Summary:
- @Controller is used for traditional web applications and is suitable for handling requests where views need to be rendered.
- @RestController is used for building RESTful web services, where the response is typically in the form of data (JSON or XML) rather than a rendered view.
- @RestController is a specialization of @Controller with the addition of @ResponseBody on every method, making it convenient for building RESTful APIs.
In summary, choose @Controller when building web applications with views, and use @RestController when building RESTful web services that return data directly in the response body.
Q4. Differentiate between HashMap and HashTable.
Ans: Here's a comparison of HashMap and Hashtable in tabular form:
Feature |
HashMap |
Hashtable |
Synchronization |
Not synchronized by default. Can be synchronized externally using Collections.synchronizedMap(). |
Synchronized by default. All methods are synchronized. |
Null Values |
Allows null values for both keys and values. |
Neither keys nor values can be null. |
Performance |
Generally better performance due to lack of synchronization. Preferred for single-threaded or low-concurrency scenarios. |
Performance can degrade in high-concurrency scenarios due to synchronization. |
Iterators |
Fail-fast iterators. If the map is modified structurally while an iterator is in progress, it throws ConcurrentModificationException. |
Fail-fast iterators. |
Example Usage:
// HashMap example
Map<String, String> hashMap = new HashMap<>();
hashMap.put("key1", "value1");
hashMap.put("key2", "value2");
// Hashtable example
Hashtable<String, String> hashtable = new Hashtable<>();
hashtable.put("key1", "value1");
hashtable.put("key2", "value2");
Recommendations:
- Use HashMap when synchronization is not needed, or when external synchronization is acceptable.
- For new code and in scenarios requiring concurrent access, consider using ConcurrentHashMap or Collections.synchronizedMap(new HashMap<>()) for better performance and flexibility.
If you need a synchronized map and are working with legacy code, Hashtable can be used.
Q5. When to use interface and when to use abstract class?
Ans: The choice between using an interface and an abstract class in Java depends on the specific requirements and design goals of your application. Here are some considerations to help you decide when to use an interface and when to use an abstract class:
Use Interface When:
1. Multiple Inheritance:
- Java supports multiple inheritance through interfaces, allowing a class to implement multiple interfaces.
- If a class needs to inherit behaviors from multiple sources, interfaces are a suitable choice.
2. Contract without Implementation:
- Interfaces allow you to define a contract (method signatures) without providing an implementation.
- Useful when you want to ensure that multiple classes adhere to a specific set of methods without dictating the implementation details.
3. Encapsulation:
- Interfaces help achieve better encapsulation by separating the definition of methods from the details of their implementation.
- Implementing classes can provide their own implementation details while adhering to the interface contract.
4. Loose Coupling:
- Using interfaces promotes loose coupling between classes. Classes that interact through interfaces are less dependent on each other's internal details.
5. API Design:
- Interfaces are often used to design APIs (Application Programming Interfaces) where you want to provide a set of functionalities that can be implemented by different classes.
Use Abstract Class When:
1. Common Base Class:
- If you have a common base class that contains shared implementation details, use an abstract class.
- Abstract classes can provide a mix of abstract (unimplemented) and concrete (implemented) methods.
2. Code Reusability:
- Abstract classes support code reusability by allowing the reuse of common implementation across multiple subclasses.
- Subclasses can inherit both state (fields) and behavior (methods) from the abstract class.
3. Constructors:
- Abstract classes can have constructors, allowing you to perform common initialization tasks when an object is created.
- Constructors in interfaces were introduced in Java 9 but are not as flexible as those in abstract classes.
4. Partial Implementation:
- Abstract classes can have both abstract and concrete methods, providing a partial implementation that subclasses can choose to override or inherit.
5. Access Modifiers:
- Abstract classes can have access modifiers on their fields and methods, allowing better control over the visibility of members.
// Interface example
interface Shape {
void draw();
}
// Abstract class example
abstract class Animal {
abstract void makeSound();
void eat() {
System.out.println("Animal is eating.");
}
}
Guidelines:
- If you need to provide a common base class, share code, or define some common state, use an abstract class.
- If you want to define a contract for classes to implement without providing any shared implementation, use an interface.
- In some cases, a combination of both interfaces and abstract classes may be appropriate for a flexible and extensible design.
Q6. How to declare a class as static in java?
Ans: In Java, you cannot declare a top-level class (i.e., a class directly within a package) as static. The static keyword is used for class members (fields and methods) and nested classes within another class. Here's how you can use static within a class:
1. Static Nested Class:
- A static nested class is a nested class that is declared with the static keyword.
- It can be accessed using the enclosing class name.
public class OuterClass {
// Outer class members
static class NestedStaticClass {
// Static nested class members
}
}
Usage:
OuterClass.NestedStaticClass nestedObj = new OuterClass.NestedStaticClass();
2. Static Methods and Fields:
- You can declare methods and fields as static within a class.
- These methods and fields belong to the class itself, not to instances of the class.
public class MyClass {
static int staticField;
static void staticMethod() {
// Static method implementation
}
}
Usage:
MyClass.staticField = 42;
MyClass.staticMethod();
3. Static Initialization Block:
- You can use a static initialization block to perform actions when the class is loaded.
- The static block is executed when the class is first loaded, and it runs only once.
public class MyClass {
static {
// Static initialization block
}
}
Remember, the static keyword is not used to declare top-level classes. Top-level classes are implicitly static in the sense that they can be accessed without creating an instance of the enclosing package. If you need to group related classes, consider using packages or inner classes within another class.
Q7. Can we make the constructor private?
Ans: Yes, you can make a constructor private in Java. Making a constructor private is a common practice when you want to enforce a certain design pattern, such as the Singleton pattern, or when you want to create utility classes that should not be instantiated.
Here's an example of a private constructor:
public class MyClass {
private MyClass() {
// Private constructor implementation
}
public static void main(String[] args) {
// You cannot instantiate MyClass using the constructor
// MyClass obj = new MyClass(); // This would result in a compilation error
// Instead, you can use other methods or static members of the class
MyClass.doSomething();
}
public static void doSomething() {
System.out.println("Doing something...");
}
}
In this example, the constructor private MyClass() is not accessible from outside the class, so you cannot create an instance of MyClass using new MyClass(). However, you can still use other methods or static members of the class.
As mentioned earlier, one common use case for private constructors is the Singleton pattern, where you want to ensure that only one instance of the class can be created. Here's an example of a Singleton class with a private constructor:
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
// Private constructor implementation
}
public static Singleton getInstance() {
return INSTANCE;
}
}
In this Singleton pattern, the only way to obtain an instance of Singleton is through the static method getInstance(). The private constructor ensures that no other class can directly instantiate it.
Q8. Write a program for string reversal eg. if input is “abcd” then output should be: dcba.
Ans: Certainly! You can reverse a string in Java using various approaches. Here's a simple program using the StringBuilder class:
public class StringReversal {
public static void main(String[] args) {
String input = "abcd";
String reversed = reverseString(input);
System.out.println("Original: " + input);
System.out.println("Reversed: " + reversed);
}
private static String reverseString(String input) {
// Using StringBuilder to efficiently reverse the string
return new StringBuilder(input).reverse().toString();
}
}
In this example, the reverseString method takes an input string, converts it to a StringBuilder, reverses it using the reverse() method, and then converts it back to a string using toString().
You can run this program, and the output should be:
Original: abcd
Reversed: dcba
Q9. Why do we use enum when constants are there?
Ans: Enums in Java provide a way to represent a fixed set of constants with more structure and type-safety compared to using plain constants. Here are some reasons why you might prefer enums over plain constants:
1. Type Safety:
- Enums are types, which means they provide type safety. You can't accidentally assign a value that doesn't belong to the set of constants defined in the enum.
- With plain constants, you might use primitive data types or strings to represent constants, and mistakes can occur due to typos or incorrect assignments.
2. Readability and Expressiveness:
- Enums can make your code more readable by providing meaningful names for constant values.
- Enums can be used to represent a set of related constants, making the code more expressive.
3. Grouping Related Constants:
- Enums allow you to group related constants together in a single type.
- This helps in organizing constants and provides a clear structure to your code.
3. Iterating Over Constants:
- Enums can be easily iterated over using the values() method, which is useful in scenarios where you need to perform operations on all constants.
4. Switch Statements:
- Enums work well with switch statements. Switching on enums is more readable and less error-prone than switching on integer or string constants.
5. Adding Methods and Behavior:
- Enums can have methods and behavior associated with them, allowing you to attach functionality to each constant.
- Plain constants are usually just static final fields without the ability to include behavior.
Example:
enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;
public boolean isWeekend() {
return this == SATURDAY || this == SUNDAY;
}
}
public class EnumExample {
public static void main(String[] args) {
Day today = Day.MONDAY;
System.out.println("Is today a weekend? " + today.isWeekend());
}
}
In this example, the Day enum represents days of the week, and it includes a method isWeekend() to check if a given day is a weekend. Enums provide a more structured way to represent and work with constants in this scenario.
Q10. Find length of longest substring.
Ans: To find the length of the longest substring without repeating characters, you can use the sliding window approach. Here's a Java program that demonstrates how to achieve this:
import java.util.HashMap;
public class LongestSubstring {
public static void main(String[] args) {
String input = "abcabcbb";
int length = lengthOfLongestSubstring(input);
System.out.println("Length of the longest substring without repeating characters: " + length);
}
private static int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) {
return 0;
}
int maxLength = 0;
int left = 0;
HashMap<Character, Integer> charIndexMap = new HashMap<>();
for (int right = 0; right < s.length(); right++) {
char currentChar = s.charAt(right);
if (charIndexMap.containsKey(currentChar)) {
// Move the left pointer to the right of the previous occurrence of the character
left = Math.max(left, charIndexMap.get(currentChar) + 1);
}
// Update the index of the current character
charIndexMap.put(currentChar, right);
// Update the maximum length
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}
}
This program defines a function lengthOfLongestSubstring that takes a string as input and returns the length of the longest substring without repeating characters. The sliding window is represented by the variables left and right, and a HashMap is used to store the index of each character.
You can change the value of the input variable to test the function with different strings. In the provided example, the input is "abcabcbb", and the output will be:
Length of the longest substring without repeating characters: 3
This means that the longest substring without repeating characters in "abcabcbb" is "abc"
Add a comment: