Java is one of the most popular and flexible programming languages in the constantly changing world of technology. The need for Senior Java Developers is growing as more companies look for qualified developers to improve their software solutions. To assist interviewers and candidates in navigating the complexities of the recruiting process, this article explores the broad field of Senior Java Developer interview questions, including everything from technical skills to soft skills.
25+ Interview Questions for Senior Java Developer
1. Implement a thread-safe Singleton class in Java.
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2. Use the Executor framework to create a simple multi-threaded program in Java.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ConcurrentTaskExecutor {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable task = new MyTask(i);
executor.execute(task);
}
executor.shutdown();
}
}
class MyTask implements Runnable {
private int taskId;
public MyTask(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("Task ID: " + taskId + ", Thread ID: " + Thread.currentThread().getId());
}
}
3. Create a custom comparator to sort a list of custom objects based on a specific attribute.
import java.util.Comparator;
import java.util.List;
import java.util.Collections;
public class CustomObjectSorting {
public static void main(String[] args) {
List<MyObject> myList; // initialize list with custom objects
Collections.sort(myList, Comparator.comparing(MyObject::getSomeAttribute));
// myList is now sorted based on the 'someAttribute' of MyObject
}
}
class MyObject {
private int someAttribute;
public int getSomeAttribute() {
return someAttribute;
}
}
4. Read data from a file and write it into another file in Java.
import java.io.FileReader;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
public class FileIOOperations {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"));
BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
5. Create a simple binary tree structure and implement in-order traversal.
class TreeNode {
int data;
TreeNode left, right;
public TreeNode(int data) {
this.data = data;
this.left = this.right = null;
}
}
public class BinaryTree {
TreeNode root;
public BinaryTree() {
root = null;
}
public void inOrderTraversal(TreeNode node) {
if (node != null) {
inOrderTraversal(node.left);
System.out.print(node.data + " ");
inOrderTraversal(node.right);
}
}
public static void main(String[] args) {
BinaryTree tree = new BinaryTree();
// Build the tree
// Perform in-order traversal
tree.inOrderTraversal(tree.root);
}
}
6. Create a custom exception and handle it in a Java program.
class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
}
public class ExceptionHandling {
public static void main(String[] args) {
try {
throw new CustomException("This is a custom exception.");
} catch (CustomException e) {
System.out.println("Caught custom exception: " + e.getMessage());
}
}
}
7. Write a Java program to make an HTTP GET request to a REST API.
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class RestClient {
public static void main(String[] args) {
try {
URL url = new URL("https://api.example.com/data");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
System.out.println("API Response: " + response.toString());
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
8. Connect to a database using JDBC and execute a simple query.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JdbcExample {
public static void main(String[] args) {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "username", "password");
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM mytable");
while (resultSet.next()) {
System.out.println(resultSet.getString("column1") + " " + resultSet.getString("column2"));
}
resultSet.close();
statement.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
9. Create a simple thread pool implementation in Java.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CustomThreadPool {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable task = new MyTask(i);
executor.execute(task);
}
executor.shutdown();
}
}
class MyTask implements Runnable {
private int taskId;
public MyTask(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("Task ID: " + taskId + ", Thread ID: " + Thread.currentThread().getId());
}
}
10. Design a simple caching mechanism in Java.
import java.util.Map;
import java.util.HashMap;
public class SimpleCache {
private Map<String, Object> cache;
public SimpleCache() {
this.cache = new HashMap<>();
}
public void put(String key, Object value) {
cache.put(key, value);
}
public Object get(String key) {
return cache.get(key);
}
public void clear() {
cache.clear();
}
public static void main(String[] args) {
SimpleCache cache = new SimpleCache();
cache.put("key1", "value1");
cache.put("key2", "value2");
System.out.println("Value for key1: " + cache.get("key1"));
}
}
11. Create a simple REST API using Spring Boot.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class SpringRestApiApplication {
public static void main(String[] args) {
SpringApplication.run(SpringRestApiApplication.class, args);
}
}
@RestController
class HelloController {
@GetMapping("/hello")
public String sayHello() {
return "Hello, Spring Boot!";
}
}
12. Create a Spring MVC controller with request mapping.
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
@GetMapping("/welcome")
public String welcome() {
return "welcomePage";
}
}
13. Use Spring Boot Data JPA to perform CRUD operations on a database entity.
import org.springframework.data.jpa.repository.JpaRepository;
import javax.persistence.Entity;
import javax.persistence.Id;
interface UserRepository extends JpaRepository<User, Long> {
}
@Entity
class User {
@Id
private Long id;
private String username;
private String email;
// Getters and setters
}
14. Create a RESTful web service using Jersey.
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@Path("/hello")
public class HelloWorldResource {
@GET
public String sayHello() {
return "Hello, Jersey!";
}
}
15. Configure Spring Boot Security for authentication and authorization.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build());
return manager;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/public/").permitAll().anyRequest().authenticated().and().formLogin();
}
}
16. Use `CompletableFuture` for asynchronous programming in Java.
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String[] args) {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
// Perform asynchronous task
System.out.println("Task running asynchronously");
});
// Additional processing
future.thenRun(() -> System.out.println("Additional processing after task completion"));
}
}
17. Implement the producer-consumer pattern using `BlockingQueue` in Java.
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ProducerConsumerExample {
private static final int CAPACITY = 5;
private static final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(CAPACITY);
public static void main(String[] args) {
Thread producer = new Thread(new Producer());
Thread consumer = new Thread(new Consumer());
producer.start();
consumer.start();
}
static class Producer implements Runnable {
@Override
public void run() {
try {
for (int i = 1; i <= 10; i++) {
queue.put(i);
System.out.println("Produced: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Consumer implements Runnable {
@Override
public void run() {
try {
for (int i = 1; i <= 10; i++) {
int consumed = queue.take();
System.out.println("Consumed: " + consumed);
Thread.sleep(2000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
18. Implement memoization to optimize a recursive function.
import java.util.HashMap;
import java.util.Map;
public class MemoizationExample {
private static Map<Integer, Integer> memo = new HashMap<>();
public static void main(String[] args) {
int n = 5;
int result = fibonacci(n);
System.out.println("Fibonacci(" + n + ") = " + result);
}
private static int fibonacci(int n) {
if (n <= 1) {
return n;
}
if (memo.containsKey(n)) {
return memo.get(n);
}
int fib = fibonacci(n 1) + fibonacci(n 2);
memo.put(n, fib);
return fib;
}
}
19. Create a custom annotation and use it in a Java class.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {
String value() default "Default Value";
}
public class AnnotatedClass {
@CustomAnnotation(value = "Custom Value")
public void annotatedMethod() {
// Method implementation
}
}
20. Use `CompletableFuture` with exception handling in Java.
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExceptionHandling {
public static void main(String[] args) {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
// Simulate an exception
throw new RuntimeException("Simulated exception");
});
future.exceptionally(ex -> {
System.out.println("Exception occurred: " + ex.getMessage());
return null;
});
}
}
21. Create a WebSocket server using Spring.
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
@Controller
public class WebSocketController {
@MessageMapping("/hello")
@SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
Thread.sleep(1000);
return new Greeting("Hello, " + message.getName() + "!");
}
}
22. Create a WebSocket client using Spring.
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.simp.stomp.StompSessionHandler;
import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.messaging.WebSocketStompClient;
public class WebSocketClient {
public static void main(String[] args) {
WebSocketStompClient stompClient = new WebSocketStompClient(new StandardWebSocketClient());
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
StompSessionHandler sessionHandler = new MyStompSessionHandler();
stompClient.connect("ws://localhost:8080/gs-guide-websocket", sessionHandler);
}
static class MyStompSessionHandler extends StompSessionHandlerAdapter {
// Handle Stomp session events
}
}
23. Configure JWT (JSON Web Token) authentication in a Spring Security application.
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// Implement user retrieval logic (from database, LDAP, etc.)
return User.withUsername(username)
.password("password") // Replace with actual password retrieval
.roles("USER")
.build();
}
}
24. Use Resilience4j to implement the Circuit Breaker pattern in a Java application.
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.stereotype.Service;
@Service
public class MyService {
private final CircuitBreaker circuitBreaker;
public MyService(CircuitBreakerRegistry circuitBreakerRegistry) {
this.circuitBreaker = circuitBreakerRegistry.circuitBreaker("myCircuitBreaker");
}
@CircuitBreaker(name = "myCircuitBreaker", fallbackMethod = "fallbackMethod")
public String performOperation() {
// Implement the operation to be protected by the circuit breaker
// ...
if (/* Operation fails */) {
throw new RuntimeException("Operation failed");
}
return "Operation successful";
}
public String fallbackMethod(Throwable throwable) {
return "Fallback response";
}
}
25. Use Bucket4j to implement rate limiting in a Java application.
import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket;
import io.github.bucket4j.Bucket4j;
import io.github.bucket4j.Refill;
import java.time.Duration;
public class RateLimitingExample {
public static void main(String[] args) {
Bandwidth limit = Bandwidth.classic(10, Refill.intervally(10, Duration.ofMinutes(1)));
Bucket bucket = Bucket4j.builder().addLimit(limit).build();
for (int i = 0; i < 15; i++) {
if (bucket.tryConsume(1)) {
System.out.println("Request " + i + " processed");
} else {
System.out.println("Rate limit exceeded for request " + i);
}
}
}
}
These coding questions cover a wide range of topics relevant to a Senior Java Developer’s role, including core Java concepts, concurrency, data structures, algorithms, Spring framework, database connectivity, web development, and advanced topics like asynchronous programming, memoization, custom annotations, WebSocket, and resilience patterns.
Key Responsibilities of Senior Java Developer and Mid-Senior Java Developer
Key Responsibilities | Senior Java Developer | Mid-Senior Java Developer |
Software Development | Lead and participate in the design and development of complex Java applications.Provide mentorship and guidance to junior developers on best practices.Engage in collaboration with cross-functional teams. | Contribute actively to the design and development of Java applications.Collaborate with team members on coding and implementation.Work on moderate complex software tasks. |
Architecture and Design | Plan and design scalable and maintainable software systems.Assess and recommend technologies and frameworks.Ensure compliance with coding standards and design principles. | Participate in the architectural design of software solutions.Implement features according to design specifications.Adhere to established design patterns and coding standards. |
Code Review and Quality Assurance | Perform code reviews to guarantee code quality and adherence to standards.Implement and maintain automated testing processes.Identify and address code vulnerabilities and performance bottlenecks. | Take part in code reviews to guarantee the quality of the code.Write unit tests and perform manual testing as needed.Collaborate with QA teams to resolve issues. |
Technical Leadership | Lead development teams technically and offer advice.Keep abreast of market developments and assist the group in implementing new technology.Solve complex technical challenges. | Demonstrate technical leadership within the project teams.Stay informed about emerging technologies.Assist in solving technical issues and challenges. |
Collaboration and Communication | Work collaboratively with cross-functional teams, including product managers and UI/UX designers.Communicate efficiently with team members and stakeholders.Lead and facilitate technical discussions. | Foster collaboration with team members and other stakeholders.Maintain effective communication within the team.Participate in technical discussions. |
Troubleshooting and Support | Investigate and troubleshoot production issues.Offer direction and technical support to address problems.Implement solutions to enhance system reliability. | Assist in troubleshooting production issues.Provide support to resolve technical problems.Contribute to solutions for enhancing system reliability. |
Agile Development | Utilize Scrum and Agile working methods.Take part in stand-ups, retrospectives, and sprint planning.Provide accurate estimations for development tasks. | Work in Agile/Scrum environments.Participate in daily stand-ups and sprint planning.Provide estimations for development efforts. |
Documentation | Create and maintain technical documentation.Document architectural decisions and code implementations.Ensure documentation aligns with industry standards. | Contribute to technical documentation.Document code changes and implementations.Follow documentation standards. |
Continuous Learning | Stay updated on Java and related technologies.Continuous learning and skill development.Share knowledge and insights with the team. | Keep abreast of Java and relevant technologies.Engage in ongoing learning and skills enhancement.Participate in sessions of knowledge sharing. |
Team Collaboration | Promote cooperation and a positive team culture.Provide guidance and support to team members.Encourage knowledge sharing within the team. | Contribute to a positive team culture.Collaborate with team members effectively.Share knowledge and experiences with the team. |
Note: The responsibilities listed are indicative and may vary based on specific job roles and organizational structures. Adjustments can be made based on the company’s requirements and the evolving needs of the development team.
How much do Senior Java Developers earn?
The salary for Senior Java Developers fluctuates depending on factors such as experience, location, and industry. As of 2022, the average annual salary for Senior Java Developers in the United States is approximately $120,000 to $140,000. However, salaries can range from $100,000 for those with less experience to over $160,000 for those with extensive expertise. In the United Kingdom, Senior Java Developers earn an average annual salary ranging from £60,000 to £80,000. How much does a Mid-Senior Java Developer earn?
How much does a Mid-Senior Java Developer earn?
For Mid-Senior Java Developers, the average annual salary is slightly lower, reflecting their intermediate level of experience. Mid-senior Java Developers in the United States typically receive salaries ranging from $90,000 to $110,000 annually. In the United Kingdom, the average yearly salary for Mid-Senior Java Developers is around £45,000 to £60,000.
Note: These statistics might have undergone alterations, thus it is recommended to refer to the most recent salary surveys and market analyses for the latest and current information.
Conclusion
In conclusion, these Java Developer interview questions cover a broad spectrum of technical and non-technical aspects, helping organizations assess the skills and capabilities of candidates effectively. Whether evaluating problem-solving skills, understanding system architecture, or exploring soft skills and experience, these questions serve as a valuable resource for both interviewers and candidates in the competitive realm of Java development.