Preparing for a Java developer job interview? If yes, you’re probably wondering what kind of questions you can expect. To help you out, I have put together a list of 60 core Java interview questions with answers, sample code, and references.
These questions cover a wide range of basic core Java concepts. This post will help you prepare for your next interview and increase your chances of landing the job. Let’s get started!
Core Java Interview Questions
What is Java?
Java is a high-level, object-oriented programming language designed for application development. It was developed by James Gosling at Sun Microsystems and released in 1995. Java is platform-independent, which means that code written in Java can be executed on any platform that supports the Java Virtual Machine (JVM).
Reference: https://www.oracle.com/java/technologies/
Explain the main difference between JDK, JRE, and JVM.
- JDK (Java Development Kit): A software development environment used for developing Java applications. It includes the Java Runtime Environment (JRE), an interpreter/loader (Java), a compiler (javac), an archiver (jar), and other tools.
- JRE (Java Runtime Environment): A software package that contains the libraries and JVM required to run Java applications.
- JVM (Java Virtual Machine): A virtual machine that interprets and executes Java bytecode, providing a platform-independent execution environment for Java programs.
Reference: https://www.geeksforgeeks.org/differences-jdk-jre-jvm/
What is the difference between ‘==’ and ‘equals()’ in Java?
‘==’ is a reference comparison operator that checks if two references point to the same object in memory, while ‘equals()’ is a method that checks if two objects have the same content based on their implementation.
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false, different references
System.out.println(s1.equals(s2)); // true, same content
Reference: https://www.geeksforgeeks.org/difference-equals-method-java/
What are the different access modifiers in Java?
Answer: Java has four access modifiers:
- Public: Accessible from any class.
- Protected: Accessible within the same package and subclasses in other packages.
- Default (package-private): Accessible within the same package.
- Private: Accessible only within the class.
public class MyClass {
public int publicVar; // can be accessed from anywhere
protected int protectedVar; // can be accessed from within the same class, subclass, and package
int defaultVar; // can be accessed from within the same class and package
private int privateVar; // can only be accessed from within the same class
public void myMethod() {
// method code here
}
protected void myProtectedMethod() {
// method code here
}
void myDefaultMethod() {
// method code here
}
private void myPrivateMethod() {
// method code here
}
}
Reference: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/doc-files/Modifers.html
What is the difference between an abstract class and an interface?
- Abstract class: A class that cannot be instantiated and can have both abstract (unimplemented) and non-abstract methods.
- Interface: A collection of abstract methods (prior to Java 8) and default or static methods (Java 8 onwards) that can be implemented by any class. A class can implement multiple interfaces.
// Example of an abstract class
abstract class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public abstract void makeSound();
public void eat() {
System.out.println(name + " is eating.");
}
}
// Example of an interface
interface Mammal {
public void giveBirth();
}
// Example of a class that extends an abstract class and implements an interface
class Dog extends Animal implements Mammal {
public Dog(String name) {
super(name);
}
public void makeSound() {
System.out.println(name + " says woof.");
}
public void giveBirth() {
System.out.println(name + " is giving birth to puppies.");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog("Buddy");
myDog.makeSound(); // Output: Buddy says woof.
myDog.eat(); // Output: Buddy is eating.
myDog.giveBirth(); // Output: Buddy is giving birth to puppies.
}
}
In this example, Animal
is an abstract class that defines a name
variable and an abstract method makeSound()
. The Dog
class extends Animal
and implements the Mammal
interface, which requires it to implement the giveBirth()
method. The Dog
class provides implementations for both makeSound()
and giveBirth()
.
The key difference between an abstract class and an interface is that an abstract class can have both abstract and non-abstract methods, while an interface can only have abstract methods. Additionally, a class can only extend one abstract class, but can implement multiple interfaces.
References
Here’s the link to the Java API documentation on abstract classes: https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
And here’s the link to the Java API documentation on interfaces: https://docs.oracle.com/javase/tutorial/java/concepts/interface.html
What is method overloading and method overriding in Java?
- Method overloading: Defining multiple methods with the same name but different parameters in the same class.
- Method overriding: When a subclass provides a new implementation for a method that already exists in its superclass.
// Method Overloading
class OverloadingExample {
void display(int a) { ... }
void display(int a, int b) { ... }
}
// Method Overriding
class SuperClass {
void display() { ... }
}
class SubClass extends SuperClass {
@Override
void display() { ... }
}
Reference
What is the difference between final, finally, and finalize() in Java?
- final: A keyword used to restrict modification. It can be applied to variables (making them constant), methods (preventing them from being overridden), or classes (preventing them from being extended).
- finally: A block used with try-catch statements to ensure that code is executed, regardless of whether an exception is thrown or not.
- finalize(): A method in the Object class that is called by the garbage collector before an object is reclaimed. It can be overridden to perform cleanup tasks.
public class FinalExample {
// final variable cannot be reassigned
public final int myNumber = 42;
public static void main(String[] args) {
try {
// try block with potential exception
} catch (Exception e) {
// catch block to handle exception
} finally {
// finally block will always execute, whether or not an exception is thrown
}
}
@Override
protected void finalize() throws Throwable {
// finalize() method is called by the garbage collector before an object is destroyed
}
}
References
What is the difference between ArrayList and LinkedList in Java?
ArrayList and LinkedList are two classes implementing the List interface, but they have different underlying data structures:
- ArrayList: Uses a dynamic array, provides fast random access and insertion/removal at the end, but slow insertion/removal in the middle.
- LinkedList: Uses a doubly-linked list, provides fast insertion/removal at the beginning and in the middle, but slow random access.
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListExample {
public static void main(String[] args) {
// ArrayList example
List<String> arrayList = new ArrayList<>();
arrayList.add("Apple");
arrayList.add("Banana");
arrayList.add("Cherry");
// LinkedList example
List<String> linkedList = new LinkedList<>();
linkedList.add("Apple");
linkedList.add("Banana");
linkedList.add("Cherry");
// Accessing elements in ArrayList
System.out.println("Accessing elements in ArrayList:");
for (int i = 0; i < arrayList.size(); i++) {
System.out.println(arrayList.get(i));
}
// Accessing elements in LinkedList
System.out.println("Accessing elements in LinkedList:");
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
// Adding an element to the beginning of ArrayList
arrayList.add(0, "Grape");
System.out.println("ArrayList after adding an element to the beginning: " + arrayList);
// Adding an element to the beginning of LinkedList
linkedList.add(0, "Grape");
System.out.println("LinkedList after adding an element to the beginning: " + linkedList);
// Removing an element from the middle of ArrayList
arrayList.remove(1);
System.out.println("ArrayList after removing an element from the middle: " + arrayList);
// Removing an element from the middle of LinkedList
linkedList.remove(1);
System.out.println("LinkedList after removing an element from the middle: " + linkedList);
}
}
Reference
What is the Collections Framework in Java?
The Collections Framework is a set of interfaces and classes in Java that provide data structures and algorithms for storing and manipulating objects. The main interfaces are Collection, List, Set, Queue, and Map. Some commonly used classes include ArrayList, LinkedList, HashSet, TreeSet, PriorityQueue, and HashMap.
Reference: https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/package-summary.html
Explain the difference between HashMap, TreeMap, and LinkedHashMap.
These are three classes implementing the Map interface in Java.
The HashMap
class is the most basic implementation of the Map
interface, and it uses hashing to store the key-value pairs. The order of the keys is not guaranteed, and it can change if the map is resized. You can find more information about HashMap
in the Java API docs here.
The TreeMap
class uses a binary search tree to store the key-value pairs, and the keys are sorted in natural order or based on a specified Comparator
. This means that the keys are always in order when you iterate over the map. You can find more information about TreeMap
in the Java API docs here.
The LinkedHashMap
class is similar to HashMap
, but it maintains the insertion order of the key-value pairs. This means that the keys are in the same order that they were added to the map. You can find more information about LinkedHashMap
in the Java API docs here.
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.TreeMap;
public class MapExample {
public static void main(String[] args) {
// HashMap example
HashMap<String, Integer> hashMap = new HashMap<>();
hashMap.put("one", 1);
hashMap.put("two", 2);
hashMap.put("three", 3);
System.out.println("HashMap: " + hashMap);
// TreeMap example
TreeMap<String, Integer> treeMap = new TreeMap<>();
treeMap.put("one", 1);
treeMap.put("three", 3);
treeMap.put("two", 2);
System.out.println("TreeMap: " + treeMap);
// LinkedHashMap example
LinkedHashMap<String, Integer> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("one", 1);
linkedHashMap.put("two", 2);
linkedHashMap.put("three", 3);
System.out.println("LinkedHashMap: " + linkedHashMap);
}
}
This code creates three different types of maps and adds the same key-value pairs to each of them. When the maps are printed, you can see that they are in different orders:
HashMap: {three=3, two=2, one=1}
TreeMap: {one=1, three=3, two=2}
LinkedHashMap: {one=1, two=2, three=3}
What is a Java annotation?
Annotations are metadata that provide information about the code, which can be parsed by the compiler or used by tools during runtime. They can be applied to classes, methods, fields, parameters, or other program elements. Some built-in annotations include @Override, @Deprecated, and @SuppressWarnings.
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
String value();
}
public class MyClass {
@MyAnnotation("example")
public void myMethod() {
// do something
}
}
In this example, we define a custom annotation called @MyAnnotation
with a single parameter called value
, which takes a string as its value. We then apply this annotation to the myMethod()
method in the MyClass
class.
Explain the difference between checked and unchecked exceptions in Java.
Checked exceptions are exceptions that must be explicitly caught or declared in the method signature using the ‘throws’ keyword (e.g., IOException). Unchecked exceptions are exceptions that do not need to be declared or caught, typically indicating a programming error (e.g., NullPointerException, ArrayIndexOutOfBoundsException).
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class ExceptionExample {
public static void main(String[] args) {
// Checked exception example
try {
File file = new File("file.txt");
Scanner scanner = new Scanner(file); // This statement may throw FileNotFoundException
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// Unchecked exception example
int[] arr = {1, 2, 3};
int x = arr[3]; // This statement may throw ArrayIndexOutOfBoundsException
}
}
In the above code, the first example demonstrates a checked exception FileNotFoundException
. This means that the compiler forces you to either handle the exception or declare it in the method signature. In this case, we catch the exception and print the stack trace.
The second example demonstrates an unchecked exception ArrayIndexOutOfBoundsException
. This means that the compiler does not force you to handle the exception or declare it in the method signature. However, the exception can still occur at runtime and cause the program to crash if not handled properly.
Reference
What is the purpose of the serialVersionUID field in Java?
serialVersionUID is a unique identifier for a serializable class. It is used during deserialization to verify that the sender and receiver of a serialized object have the same class definition. If serialVersionUID values do not match, an InvalidClassException is thrown.
import java.io.*;
public class Employee implements java.io.Serializable {
public String name;
public String address;
public transient int SSN;
public int employeeID;
public static final long serialVersionUID = 123456789;
public void mailCheck() {
System.out.println("Mailing a check to " + name + " at " + address);
}
}
In the above code, the Employee
class implements the java.io.Serializable
interface, which means that its objects can be serialized (i.e., converted to a byte stream) and deserialized (i.e., converted back to an object). The serialVersionUID
field is a unique identifier for the serialized version of the class, and it is used to ensure that the correct version of the class is used during deserialization.
If the serialVersionUID
value of the serialized object and the serialVersionUID
value of the deserialized object do not match, a InvalidClassException
is thrown.
Reference: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/Serializable.html
What is the difference between a shallow copy and a deep copy in Java?
- Shallow copy: Creates a new object with the same values for its fields as the original object. If the original object contains references to other objects, the shallow copy shares the same references. Changes in the original object’s referenced objects will affect the copied object.
- Deep copy: Creates a new object with the same values for its fields as the original object, and also recursively creates copies of all referenced objects. Changes in the original object’s referenced objects will not affect the copied object.
import java.util.ArrayList;
import java.util.Arrays;
public class CopyExample {
public static void main(String[] args) {
// Create an ArrayList with some elements
ArrayList<String> originalList = new ArrayList<>(Arrays.asList("foo", "bar", "baz"));
// Create a shallow copy of the list
ArrayList<String> shallowCopy = originalList;
// Create a deep copy of the list
ArrayList<String> deepCopy = new ArrayList<>(originalList);
// Modify the original list
originalList.add("qux");
// Print out the original list and the copies
System.out.println("Original list: " + originalList);
System.out.println("Shallow copy: " + shallowCopy);
System.out.println("Deep copy: " + deepCopy);
}
}
In this example, I created an ArrayList
of strings called originalList
, with three elements. I then created a shallow copy of the list by assigning it to a new variable called shallowCopy
, and a deep copy of the list by creating a new ArrayList
and passing the original list to its constructor.
Next, I modified the original list by adding a new element to it. Finally, we print out the original list and both copies to see the effect of the modification.
The output of the program is:
Original list: [foo, bar, baz, qux]
Shallow copy: [foo, bar, baz, qux]
Deep copy: [foo, bar, baz]
As you can see, the shallow copy and the original list are now identical, because they are both references to the same object in memory. The deep copy, on the other hand, is a completely separate object that was created by copying the contents of the original list. Therefore, it remains unchanged even though the original list was modified.
Reference: https://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html
What is the purpose of the ‘static’ keyword in Java?
The ‘static’ keyword can be used for a:
- static variable: A variable that belongs to the class rather than to instances of the class. There is only one copy of the static variable, shared by all instances of the class.
- static method: A method that belongs to the class rather than to instances of the class. It can be called without creating an object of the class and cannot access non-static members of the class.
public class Example {
// a static variable
static int count = 0;
// a static method
public static void printCount() {
System.out.println("Count is: " + count);
}
public Example() {
count++;
}
public static void main(String[] args) {
Example e1 = new Example();
Example e2 = new Example();
Example e3 = new Example();
// call the static method
Example.printCount();
}
}
Reference: https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
What is the purpose of the ‘this’ keyword in Java?
The ‘this’ keyword is a reference to the current instance of a class. It can be used to access instance variables, invoke instance methods, or pass the current object as a parameter. It is also used to call one constructor from another within the same class.
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
}
Reference: https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
What is the purpose of the ‘super’ keyword in Java?
The ‘super’ keyword is used to access members (variables or methods) of the superclass. It is commonly used to call the superclass constructor from a subclass constructor or to override methods in the subclass.
public class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public void speak() {
System.out.println("I am an animal");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void speak() {
super.speak();
System.out.println("I am a dog");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Fido");
dog.speak();
}
}
In this example, super
is used to call the constructor of the superclass Animal
from the subclass Dog
. It is also used in the overridden speak
method of Dog
to call the speak
method of Animal
before printing the additional message.
Reference: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#super()
What is the use of the ‘transient’ keyword in Java?
The ‘transient’ keyword is used to indicate that a variable should not be serialized when an object is being serialized. Transient variables are not stored in the serialized form and are assigned default values when an object is deserialized.
import java.io.Serializable;
public class MyClass implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private transient int age;
public MyClass(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
What is the difference between an inner class and a nested class in Java?
An inner class is a non-static nested class. It is associated with an instance of the outer class and can access its members (including private ones). A nested class is any class defined within another class and can be either static or non-static (inner class). A static nested class does not have access to the outer class’s instance members.
public class OuterClass {
private int x = 10;
public class InnerClass {
public void printX() {
System.out.println(x);
}
}
public static class NestedClass {
public void printHello() {
System.out.println("Hello");
}
}
}
In the above example, InnerClass
is an inner class of OuterClass
, while NestedClass
is a nested class of OuterClass
.
Reference: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Class.html#NestedClasses
What is the use of the ‘volatile’ keyword in Java?
The ‘volatile’ keyword is used to indicate that a variable’s value may be changed by multiple threads. It ensures that the value of the volatile variable is always read from and written to the main memory, ensuring visibility of the most recent value to all threads.
public class Counter {
private volatile int count;
public int getCount() {
return count;
}
public void increment() {
count++;
}
}
Reference: https://docs.oracle.com/en/java/javase/16/language/volatile-variables.html
What is a Java lambda expression?
A lambda expression is a concise way to define an anonymous function (method) that can be passed as an argument or assigned to a variable. Lambda expressions are primarily used with functional interfaces, which are interfaces with only one abstract method.
Comparator<String> stringLengthComparator = (s1, s2) -> s1.length() - s2.length();
Reference: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
What is a Java stream?
Java streams are a functional programming feature introduced in Java 8. They provide a concise way to process collections, arrays, or I/O channels using a pipeline of operations, such as filter, map, and reduce. Streams can be sequential or parallel, allowing for efficient parallel processing on multicore systems.
import java.util.Arrays;
import java.util.List;
public class StreamExample {
public static void main(String[] args) {
List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");
// Use a stream to filter and print out all words starting with "c"
words.stream()
.filter(word -> word.startsWith("c"))
.forEach(System.out::println);
}
}
This code creates a list of words, and then uses a stream to filter and print out all the words that start with the letter “c”. The filter
method is used to select only the words that meet the given criteria, and the forEach
method is used to print out each word in the resulting stream.
Reference: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/stream/package-summary.html
What is the purpose of the ‘synchronized’ keyword in Java?
The ‘synchronized’ keyword is used to ensure that only one thread can access a critical section of code (method or block) at a time. It is used to prevent race conditions and ensure thread safety in a multi-threaded environment.
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
In this example, the increment()
and getCount()
methods are both marked with the synchronized
keyword. This means that only one thread can execute these methods at a time, preventing multiple threads from accessing or modifying the count
variable simultaneously.
Reference: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Synchronized.html
What is the purpose of the ‘assert’ keyword in Java?
The ‘assert’ keyword is used to perform assertions, which are statements that check whether a condition is true during runtime. If the condition is false, an AssertionError is thrown. Assertions are typically used as a debugging tool to catch programming errors earlier in the development process.
public class Example {
public static void main(String[] args) {
int x = 5;
assert x == 10 : "x should be equal to 10";
System.out.println("x = " + x);
}
}
Reference: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/AssertionError.html
What is the Java Reflection API?
The Java Reflection API allows the inspection and manipulation of classes, interfaces, fields, methods, and constructors at runtime. It can be used to create objects, invoke methods, and access fields without knowing their names or types at compile time. Reflection is typically used in frameworks, libraries, and tools that need to interact with user-defined classes.
import java.lang.reflect.Method;
public class ReflectionExample {
public static void main(String[] args) throws Exception {
// Get the Class object for the String class
Class<?> stringClass = String.class;
// Get the declared methods of the String class
Method[] methods = stringClass.getDeclaredMethods();
// Print out the names of the declared methods
for (Method method : methods) {
System.out.println(method.getName());
}
}
}
This code retrieves the Class
object for the String
class using the class
keyword, and then uses the getDeclaredMethods()
method of the Class
object to obtain an array of all the declared methods of the String
class. Finally, the code uses a loop to print out the names of these methods.
Reference: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/reflect/package-summary.html
What is the purpose of the ‘package’ keyword in Java?
The ‘package’ keyword is used to declare a package (namespace) for a group of related classes, interfaces, and enumerations. Packages help organize code, avoid naming conflicts, and control access to classes and interfaces.
package com.example.myproject;
public class MyClass {
// class implementation goes here
}
Reference: https://docs.oracle.com/javase/tutorial/java/package/index.html
What is autoboxing and unboxing in Java?
Autoboxing and unboxing are automatic conversions between primitive types (int, float, etc.) and their corresponding wrapper classes (Integer, Float, etc.) in Java. Autoboxing occurs when a primitive type is converted to its wrapper class, while unboxing occurs when a wrapper class is converted to its primitive type.
// Autoboxing
int a = 5;
Integer b = a;
// Unboxing
Integer c = new Integer(10);
int d = c;
Reference: https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
What is the diamond problem in Java, and how does Java solve it?
The diamond problem occurs in languages that support multiple inheritance, where a class can inherit from multiple classes, leading to ambiguity in method resolution. Java solves the diamond problem by not allowing multiple inheritance for classes. Instead, it uses interfaces, which can be implemented by multiple classes, and default methods (Java 8 onwards) to provide common implementations.
// Define two interfaces with a common method
interface InterfaceA {
default void commonMethod() {
System.out.println("InterfaceA's implementation of commonMethod()");
}
}
interface InterfaceB {
default void commonMethod() {
System.out.println("InterfaceB's implementation of commonMethod()");
}
}
// Define a class that implements both interfaces
class MyClass implements InterfaceA, InterfaceB {
// Implement the commonMethod to resolve the diamond problem
public void commonMethod() {
InterfaceA.super.commonMethod(); // call InterfaceA's implementation
}
}
// Test the implementation
public class Main {
public static void main(String[] args) {
MyClass myObj = new MyClass();
myObj.commonMethod(); // Output: InterfaceA's implementation of commonMethod()
}
}
In this example, both InterfaceA
and InterfaceB
have a commonMethod()
with different implementations. The MyClass
implements both interfaces, but it has to provide its own implementation to resolve the diamond problem. By calling InterfaceA.super.commonMethod()
in its implementation, MyClass
chooses to use the implementation provided by InterfaceA
.
Reference: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/FunctionalInterface.html
What is a Java classloader?
A classloader is a Java component responsible for loading classes into the Java Virtual Machine (JVM) during runtime. It locates the bytecode of a class (usually from a .class file), loads it into memory, and creates a Class object representing the class. Java has three built-in classloaders: bootstrap, extension, and system (or application) classloaders.
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
public class ClassLoaderExample {
public static void main(String[] args) throws Exception {
// create a new URLClassLoader
File classFile = new File("MyClass.class");
URLClassLoader classLoader = new URLClassLoader(new URL[]{classFile.toURI().toURL()});
// load the class dynamically
Class<?> myClass = classLoader.loadClass("MyClass");
// create an instance of the class
Object myObject = myClass.newInstance();
// call a method on the instance
myClass.getMethod("myMethod").invoke(myObject);
}
}
Reference: https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/ClassLoader.html
What is garbage collection in Java, and how does it work?
Garbage collection is the process of automatically reclaiming memory occupied by objects that are no longer in use. In Java, garbage collection is managed by the garbage collector, which is part of the Java Virtual Machine (JVM). The garbage collector identifies unreachable objects, frees the memory occupied by these objects, and compacts the remaining memory. Java uses several garbage collection algorithms, such as the generational garbage collection and the Garbage-First (G1) collector.
public class GarbageCollectionExample {
public static void main(String[] args) {
// create a new object
Object obj = new Object();
// make obj eligible for garbage collection
obj = null;
// force garbage collection
System.gc();
}
}
In this example, we create a new object obj
of the Object
class. We then set obj
to null
, which means that it is no longer referenced by any variables. This makes obj
eligible for garbage collection. Finally, we call System.gc()
to force garbage collection.
Reference: https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/System.html#gc()
What is the difference between an object and a class in Java?
A class is a blueprint or template for creating objects, which are instances of the class. A class defines the structure, behavior, and state of objects, while an object is an instance of a class with specific values for its attributes.
public class Car {
private String make;
private String model;
private int year;
public Car(String make, String model, int year) {
this.make = make;
this.model = model;
this.year = year;
}
public String getMake() {
return make;
}
public String getModel() {
return model;
}
public int getYear() {
return year;
}
public void setMake(String make) {
this.make = make;
}
public void setModel(String model) {
this.model = model;
}
public void setYear(int year) {
this.year = year;
}
}
public class Main {
public static void main(String[] args) {
Car myCar = new Car("Toyota", "Camry", 2020); // create a new object of the Car class
System.out.println(myCar.getMake()); // prints "Toyota"
System.out.println(myCar.getModel()); // prints "Camry"
System.out.println(myCar.getYear()); // prints "2020"
}
}
In this code, Car
is a class that represents a car object. The Car
class has three instance variables (make
, model
, and year
) and several methods to get and set the values of those variables.
In the Main
class, we create a new object of the Car
class by calling the Car
constructor and passing in the values for the make
, model
, and year
instance variables. We then use the myCar
object to call the getMake()
, getModel()
, and getYear()
methods to retrieve the values of those instance variables.
Reference: https://docs.oracle.com/en/java/javase/16/docs/api/index.html.
What is the difference between ‘break’ and ‘continue’ statements in Java?
- ‘break’: Terminates the current loop (for, while, or do-while) or switch statement and transfers control to the statement following it.
- ‘continue’: Skips the remaining statements in the current iteration of a loop (for, while, or do-while) and proceeds to the next iteration.
// Using break
for (int i = 0; i < 10; i++) {
if (i == 5) {
break;
}
System.out.println(i);
}
// Using continue
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
continue;
}
System.out.println(i);
}
Reference: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html
What is the default value of instance variables in Java?
Instance variables in Java are automatically initialized with default values:
- Numeric types (byte, short, int, long, float, double): 0 or 0.0
- boolean: false
- char: ‘\u0000’ (null character)
- Reference types (objects, arrays, interfaces): null
Reference: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
What is the use of the ‘instanceof’ operator in Java?
The ‘instanceof’ operator is used to check if an object is an instance of a specified class or a subclass of that class. It can also be used to check if an object implements a specific interface. It returns a boolean value.
String s = "Hello";
boolean isString = s instanceof String; // true
Reference: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html
What is a constructor in Java, and what are its types?
A constructor is a special method in a class that is called when an object is created. It has the same name as the class and initializes the object’s state (attributes). There are two types of constructors in Java:
- Default constructor: A no-argument constructor that is automatically provided by the compiler if no constructors are explicitly defined in the class.
- Parameterized constructor: A constructor with one or more parameters, used to initialize the object with specific values.
class MyClass {
int a;
// Default constructor
MyClass() {
a = 0;
}
// Parameterized constructor
MyClass(int aValue) {
a = aValue;
}
}
Reference: https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
What is method overloading in Java? Provide an example.
Method overloading is the process of defining multiple methods with the same name but different parameters (number, type, or order) in the same class. The compiler differentiates between overloaded methods based on their method signatures.
class OverloadedMethods {
void display(int a) {
System.out.println("Int: " + a);
}
void display(double a) {
System.out.println("Double: " + a);
}
void display(int a, int b) {
System.out.println("Two Ints: " + a + ", " + b);
}
}
Reference: https://docs.oracle.com/javase/tutorial/java/javaOO/methods.html
What is method overriding in Java?
Method overriding is the process of providing a new implementation for an inherited method in a subclass. The overridden method in the subclass must have the same method signature as the method in the superclass.
class Animal {
void makeSound() {
System.out.println("The animal makes a sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("The dog barks");
}
}
Reference: https://docs.oracle.com/javase/tutorial/java/IandI/override.html
Explain the difference between an abstract class and an interface in Java.
- Abstract class: A class that cannot be instantiated and may contain abstract methods (methods without a body). Abstract classes can have fields, constructors, and concrete methods.
- Interface: A collection of abstract methods and default methods (Java 8 onwards) that can be implemented by multiple classes. Interfaces cannot have fields or constructors.
// An example abstract class
abstract class Animal {
public abstract void makeSound(); // abstract method
}
// An example interface
interface Jumpable {
public void jump(); // method signature
}
// A class that extends Animal and implements Jumpable
class Cat extends Animal implements Jumpable {
public void makeSound() {
System.out.println("Meow");
}
public void jump() {
System.out.println("Jumping");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Cat(); // abstract class reference variable
animal.makeSound(); // prints "Meow"
Jumpable jumpable = new Cat(); // interface reference variable
jumpable.jump(); // prints "Jumping"
}
}
In this example, Animal
is an abstract class that contains an abstract method makeSound()
. An abstract class cannot be instantiated, but can be extended by a subclass. The Cat
class extends Animal
and implements the Jumpable
interface, which contains a method signature jump()
. A class can implement multiple interfaces, but can only extend one abstract class. The Cat
class implements the makeSound()
and jump()
methods, and the main()
method demonstrates how a reference variable of the abstract class type Animal
and the interface type Jumpable
can be used to call the respective methods.
What is the purpose of the ‘final’ keyword in Java?
The ‘final’ keyword has three main purposes in Java:
- final variable: A variable that cannot be reassigned after it has been initialized. It creates a constant value.
- final method: A method that cannot be overridden by subclasses.
- final class: A class that cannot be extended by other classes.
public class Example {
public static void main(String[] args) {
final int num = 10;
num = 20; // This will result in a compiler error since num is final
}
}
Reference: https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/Final.html
What are Java access modifiers? List them and explain their usage.
Access modifiers control the visibility and accessibility of class members (variables, methods, inner classes). Java has four access modifiers:
- Public: Accessible from any class in any package.
- Protected: Accessible within the same package and from subclasses in other packages.
- Default (package-private): Accessible within the same package only. No keyword is used for this modifier.
- Private: Accessible within the same class only.
Reference: https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
What is the purpose of the ‘strictfp’ keyword in Java?
The ‘strictfp’ keyword ensures that floating-point calculations produce the same results on all platforms, regardless of their underlying hardware and software implementations. It can be applied to classes, interfaces, or methods.
public strictfp class FloatingPointCalculator {
public static strictfp double calculate(double x, double y) {
return x * y;
}
public static void main(String[] args) {
double result = calculate(0.1, 0.2);
System.out.println(result);
}
}
Reference: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.4
Explain the concept of exception handling in Java.
Exception handling is the process of managing errors that may occur during the execution of a program. In Java, exceptions are objects that represent errors or exceptional conditions. Java provides a try-catch-finally mechanism to handle exceptions:
try
: Contains the code that may throw an exception.catch
: Specifies the type of exception to catch and contains the code to handle the exception.finally
: Contains code that is always executed, regardless of whether an exception is thrown or not.
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Exception: " + e.getMessage());
} finally {
System.out.println("This block always executes");
}
Reference: https://docs.oracle.com/javase/tutorial/essential
What is the difference between checked and unchecked exceptions in Java?
- Checked exceptions: Exceptions that must be explicitly caught or declared in the method signature using the ‘throws’ keyword. They are usually caused by external factors, such as I/O errors, and are subclasses of java.lang.Exception.
- Unchecked exceptions: Exceptions that do not need to be explicitly caught or declared in the method signature. They are usually caused by programming errors and are subclasses of java.lang.RuntimeException or java.lang.Error.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class ExceptionExample {
public static void main(String[] args) {
// Checked Exception: FileNotFoundException
try {
File file = new File("nonexistentfile.txt");
Scanner scanner = new Scanner(file);
} catch (FileNotFoundException e) {
System.out.println("File not found exception caught");
e.printStackTrace();
}
// Unchecked Exception: ArithmeticException
try {
int result = 1 / 0;
} catch (ArithmeticException e) {
System.out.println("Arithmetic exception caught");
e.printStackTrace();
}
}
}
In the code above, the FileNotFoundException is a checked exception that can be thrown by the Scanner constructor when the file being read does not exist. Since this exception is checked, we must either catch it or declare it in a throws clause in the method signature.
The ArithmeticException is an unchecked exception that can be thrown when we attempt to divide an integer by zero. Since this exception is unchecked, we do not need to catch it or declare it in a throws clause.
Reference: https://docs.oracle.com/javase/tutorial/essential/exceptions/catchOrDeclare.html
What is the difference between ‘throw’ and ‘throws’ in Java?
- ‘throw’: Used to explicitly throw an exception from a method or a block of code.
- ‘throws’: Used in a method signature to indicate that the method may throw one or more exceptions. It delegates the responsibility of handling the exception to the calling method.
void myMethod() throws IOException {
if (fileNotFound) {
throw new FileNotFoundException("File not found");
}
}
Reference: https://docs.oracle.com/javase/tutorial/essential/exceptions/throwing.html
What is the purpose of the ‘finally’ block in Java exception handling?
The ‘finally’ block is used to specify a block of code that is always executed, regardless of whether an exception is thrown or caught. It is typically used to clean up resources, such as closing files or network connections.
Reference: https://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html
What are Java generics? Provide an example.
Java generics enable the creation of classes, interfaces, and methods that operate on different types of objects while maintaining type safety. They are typically used with collections to specify the type of elements stored in the collection.
List<String> myList = new ArrayList<String>();
myList.add("Hello");
String item = myList.get(0); // No need for explicit casting
Reference: https://docs.oracle.com/javase/tutorial/java/generics/index.html
What is a Java enumeration (enum)?
A Java enumeration (enum) is a special type of class that represents a group of constants (fixed set of values). Enums are useful for defining a limited set of possible values, such as days of the week, colors, or directions.
enum Days {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
Reference: https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
What is the difference between == and .equals() in Java?
- ==: Compares object references, not the actual content of the objects. It checks if two references point to the same object in memory.
- .equals(): Compares the content of the objects. The default implementation of .equals() in the Object class uses the == operator, but it can be overridden in subclasses to provide a custom comparison.
String s1 = new String("Hello");
String s2 = new String("Hello");
boolean refComparison = (s1 == s2); // false
boolean contentComparison = s1.equals(s2); // true
Reference: https://docs.oracle.com/javase/7/docs/api/java.base/java/lang/Object.html#equals(java.lang.Object)
What is the hashCode() method in Java? Explain its relationship with the equals() method.
The hashCode() method returns an integer hash code that represents the object. It is used by data structures such as HashMap and HashSet to efficiently store and retrieve objects. If two objects are considered equal according to their equals() method, their hashCode() methods should return the same hash code. If the hashCode() method is not properly implemented according to this contract, it can cause problems when using the object in collections.
class MyClass {
int id;
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof MyClass)) {
return false;
}
MyClass other = (MyClass) obj;
return this.id == other.id;
}
@Override
public int hashCode() {
return id;
}
}
Reference: https://docs.oracle.com/javase/7/docs/api/java.base/java/lang/Object.html#hashCode()
What is Java Serialization? Explain the purpose of the Serializable interface.
Java Serialization is the process of converting an object’s state into a byte stream, which can be persisted to a file or transmitted over a network. Deserialization is the process of reconstructing an object from a byte stream. The Serializable interface is a marker interface (without any methods) that indicates that a class is serializable. Only objects of classes that implement the Serializable interface can be serialized.
Reference: https://docs.oracle.com/javase/tutorial/essential/io/objectstreams.html
What is the purpose of the ‘transient’ keyword in Java?
The ‘transient’ keyword is used to indicate that a field should not be serialized when an object is serialized. It is typically used for fields that store temporary data or can be derived from other fields.
import java.io.Serializable;
public class MyClass implements Serializable {
private String name;
private transient int age;
public MyClass(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
Reference: https://docs.oracle.com/javase/tutorial/essential/io/objectstreams.html
What is a Java annotation? Provide an example.
A Java annotation is a type of metadata that can be added to Java source code elements, such as classes, methods, and fields. Annotations can be used by the Java compiler, Java Virtual Machine (JVM), or other tools to generate code, XML files, or other artifacts. Java provides several built-in annotations, such as @Override, @Deprecated, and @SuppressWarnings, and you can also create custom annotations.
@Override
public String toString() {
return "This is a custom toString() method";
}
Reference: https://docs.oracle.com/javase/tutorial/java/annotations/index.html
What is Java’s try-with-resources statement?
The try-with-resources statement is a feature introduced in Java 7 that simplifies the management of resources that implement the AutoCloseable interface, such as files, sockets, or database connections. The statement automatically closes the resources when the try block completes, reducing the risk of resource leaks and making the code more readable.
try (FileInputStream fis = new FileInputStream("input.txt")) {
// Use the FileInputStream
} catch (IOException e) {
// Handle the exception
} // FileInputStream is automatically closed here
Reference: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
What is the purpose of the ‘default’ keyword in Java interfaces?
The ‘default’ keyword, introduced in Java 8, allows you to provide a default implementation for a method in an interface. This feature enables interfaces to be more flexible and maintain backward compatibility when new methods are added.
interface MyInterface {
void method1();
default void method2() {
System.out.println("Default implementation of method2");
}
}
Reference: https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
What is a Java package, and what is the purpose of the ‘import’ statement?
A Java package is a group of related classes and interfaces organized in a namespace. Packages help avoid naming conflicts and make code more maintainable by organizing it into logical modules. The ‘import’ statement is used to make the classes and interfaces from a package available in your code so that you can use them without specifying their fully qualified names.
Reference: https://docs.oracle.com/javase/tutorial/java/package/index.html
What is a Java collection? Name some common collection classes and interfaces.
A Java collection is a data structure that stores and manages a group of objects. Java provides a rich set of collection classes and interfaces in the java.util package. Some common collection classes and interfaces include:
- List: An ordered collection (interface), with implementations such as ArrayList and LinkedList.
- Set: A collection with no duplicate elements (interface), with implementations such as HashSet and TreeSet.
- Queue: A collection that holds elements in the order they are processed (interface), with implementations such as LinkedList and PriorityQueue.
- Map: A collection that maps keys to values (interface), with implementations such as HashMap and TreeMap.
Reference: https://docs.oracle.com/javase/tutorial/collections/index.html
What is the difference between Iterator and ListIterator in Java?
- Iterator: An interface used to traverse a collection (e.g., List, Set) in a forward direction. It supports the methods hasNext(), next(), and remove().
- ListIterator: An interface that extends Iterator, specifically designed for List collections. It supports bidirectional traversal (forward and backward) and provides additional methods, such as hasPrevious(), previous(), and add(). It also supports indexed operations.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class IteratorVsListIteratorExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("cherry");
// Example using Iterator
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
// Example using ListIterator
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()) {
String element = listIterator.next();
System.out.println(element);
}
while (listIterator.hasPrevious()) {
String element = listIterator.previous();
System.out.println(element);
}
}
}
First, I created an Iterator by calling the iterator() method on the list. I then used the hasNext() and next() methods to iterate through the list and print each element.
Next, I created a ListIterator by calling the listIterator() method on the list. I then used the hasNext() and next() methods to iterate through the list and print each element.
Reference: https://docs.oracle.com/javase/tutorial/collections/interfaces/index.html
Conclusion
This post has covered 60 core Java interview questions along with their answers and references to help you prepare for your upcoming interview. By studying and understanding these questions, you can demonstrate your knowledge of the Java programming language and increase your chances of success in your job interview.