Java Interview Questions

Java is one of the most popular programming languages in use today. In order to be a successful Java programmer, it is important that you are confident in your knowledge of the basics. That’s why we compiled this list of frequently asked questions and answers, so that you’ll know what may come up during your interviewing process. The short answers will help you understand some of the basics in programming, which are imperative when interviewing for jobs.

1) What is Java?

Java programming language is a general-purpose programming language that is concurrent, class-based, and object-oriented. Java was originally developed by James Gosling at Sun Microsystems in 1991 as an interpreted language. Java is able to run on any machine with the java virtual machine installed (platform indepent).

Java has become one of the most popular languages over time because it can be used to create powerful applications and websites that work across all different types of devices (desktops, laptops, smartphones).

Java is a portable programming language, because java code is compiled into Java bytecode. Java bytecode can be executed by any java virtual machine implementation that meets the Java Virtual Machine specification.

2) What are the features of Java?

Object Oriented: Java supports all of the basic object oriented concepts like abstraction, inheritance and encapsulation.

Platform independent: The java programming language is platform independent, because java code is compiled into Java bytecode. The java bytecode can be executed by any java virtual machine implementation that meets the Java Virtual Machine specification. This means you don’t have to rewrite your java programs for each operating system or architecture.

Interpreted: Java is considered both interpreted and compiled. Java does not generate machine code after compiling a source file. Java program is compiled to bytecode instead. JVM (Java Virtual Machine) reads and interprets the bytecode instructions to machine code line by line.

Programming languages can be interpreted or compiled. A compiled language is converted into machine code when it’s compiled. Compiled languages are more efficient than interpreted ones because they don’t need to go through the process of interpretation every time they run. A program written in an interpreted language is not compiled into machine code. An interpreter translates the code line by line as the program is running.

Multithreading: Java is a multi-threaded programming language. It allows multiple threads to run in parallel to utilize CPU more effectively.

3) What is Java Virtual Machine?

The Java virtual machine is a Java-based execution environment for Java programs. The Java Virtual Machine (JVM) is also referred to as just the Java Runtime Environment, or JRE.

It’s the platform that allows Java code to be executed on any computer hardware and operating system without having to rewrite it in another programming language.

4) How can you compare two instances?

In Java, equality operator (==) can be used to compare two primitive types (int, long, double, char,…).

// Comparing two primitive types
int a = 5;
int b = 5;
System.out.println(a==b);            //true

However, equality operator (==) cannot be used to compare two objects. When equality operator is used with objects, it compares address references of these objects.

For instance, both i and j variables have value of 1000. If you compare these object variables using equality operator, it will return false. Because i and j are different object instances and they have different address references. Correct way to compare these instances is using equals method.

// Comparing two objects
Integer i = Integer.valueOf(1000);
Integer j = Integer.valueOf(1000);
System.out.println(i==j);            // false
System.out.println(i.equals(j));     // true

5) What is Encapsulation?

Encapsulation is used to hide the implementation details from users. Users (clients) cannot directly access or change instance variables of your class. They need to use getter/setter methods.

Consider you are creating a library and there is a Car class in this library. The variable mileage is encapsulated in the code below. It is defined as private, so that clients cannot directly access or change. To access mileage variable, clients should use public getMileage() method. To modify mileage variable, clients should use public setMileage() method.

public class Car {
  private int mileage;

  public int getMileage() {
    return mileage;

  public void setMileage(int mileage) {
    this.mileage = mileage;

You notice that setMileage() method is prone to error, because clients can set invalid (negative) values. All you have to do is add a validation code at the beginning of setMileage() method, then build and distribute fixed version of the library to your clients. Thanks to encapsulation, your clients are not directly updating mileage variable, they are using setter method. Once you give them fixed library, new validation code will be available on their applications.

public class Car {
  private int mileage;

  public int getMileage() {
    return mileage;

  public void setMileage(int mileage) {
    if (mileage < 0) {
      throw new RuntimeException("Mileage cannot be less than zero.");
    this.mileage = mileage;

6) How can you use Interfaces?

Consider a scenario like this. You are creating a FileOperations class. This class has two functionalities: 1. Compress some data and save it to a file, 2. Read from a compressed file and decompress it.

Some of your clients might prefer Zip format, some might prefer 7z or Rar formats. All these file compression methods should support 2 common operations (compressing and decompressing data). So we can create a generic FileCompressor interface and use it in FileOperations class.

FileCompressor declares 2 methods: compress, decompress. It doesn’t contain implementation logic for these methods. Because each compression method (zip, rar,7z) has its own algorithm. These algorithms should be coded in classes implementing FileCompressor interface (like ZipFileCompressor, RarFileCompressor).

public interface FileCompressor {
  byte[] compress(byte[] data);
  byte[] decompress(byte[] data);

Now you can create FileOperations class using FileCompressor interface. FileOperations class is using generic compress, decompress methods of the interface. It is up to client code which FileCompressor implementation is used.

public class FileOperations {

  void createCompressedFile(byte[] data, String outputFile, FileCompressor comp)
          throws IOException {
    byte[] compressedData = comp.compress(data);
    File file = new File(outputFile);
    Files.write(file.toPath(), compressedData);

  byte[] readCompressedFile(String inputFile, FileCompressor comp) throws IOException {
    Path path = Paths.get(inputFile);
    byte[] data = Files.readAllBytes(path);
    return comp.decompress(data);

Now let’s see client implementation. Client prefers to use ZipFileCompressor and creates an instance of this class. This zip instance is passed as a parameter to createCompressedFile method.

If our client changes his/her mind and decides to use Rar compression method, client code can be updated to use RarFileCompressor. We don’t need to make any changes to FileOperations class, because it is coded using generic FileCompressor interface.

FileCompressor zip = new ZipFileCompressor();
FileOperations fileOps = new FileOperations();
byte[] data = "Hello".getBytes(StandardCharsets.UTF_8);
fileOps.createCompressedFile(data, "hello.txt", zip);

7) What is Method Overloading?

In Java, you can create two or more methods with the same name as long as their parameters are different. MathOperations class below has two add() methods. First method is taking 2 int parameters, second method is taking 3 int parameters. This declaration is valid and it is called method overloading. In the runtime, if you call add method with 2 int arguments, the first method will be run. If you call add method with 3 int arguments instead, the second method will be run.

public class MathOperations {
  public int add(int a, int b) {
    return a + b;
  public int add(int a, int b, int c) {
    return a + b + c;

There is another example of method overloading below. In this example MathOperations has two add() methods and both methods have 2 parameters. However, types of parameters are different in these method declarations. First method takes 2 int parameters, other one takes 2 double parameters.

public class MathOperations {
  public int add(int a, int b) {
    return a + b;
  public double add(double a, double b) {
    return a + b;

8) What is the use of Inheritance?

Say, you want to create a class representing employees in a company. You can add common attributes to this class like name, lastName and employeeId. You can also add a method to print basic information about the employee.

public class Employee {
  private String name;
  private String lastName;
  private long employeeId;

  public Employee(String name, String lastName, long employeeId) { = name;
    this.lastName = lastName;
    this.employeeId = employeeId;

  public void printEmployeeInfo() {
    System.out.println(name + ", " + lastName + ": " + employeeId);

Now, let’s create another class for developers. Since a developer is also an employee, our Developer class should have common attributes (name, lastName, employeeId, printEmployeeInfo()). In Java, there is an easy way to use an existing code called Inheritance.

You can extend Developer class from Exployee class as follows. Developer class will have name, lastName, employeeId class variables and printEmployeeInfo() method, even though we didn’t code them in Developer class definition. Developer class inherits these attributes from its super class – Employee.

public class Developer extends Employee{

  public Developer(String name, String lastName, long employeeId) {
    super(name, lastName, employeeId);

  public void printJavaIDEs() {
    System.out.println("Eclipse, NetBeans, IntelliJ IDEA");

The code snippet below creates an instance of Developer class. You can call printEmployeeInfo() method with this instance, this method is inherited from Employee class.

Developer dev = new Developer("John", "Smith", 1237654);

9) What is Method Overriding?

You can inherit methods from super class using inheritance in Java. If you want to reimplement inherited method, you can update the implementation details in the subclass.

Following code show the class Planet. It has a method called displayInfo() and displays information about how planets are formed.

public class Planet {
  public void displayInfo() {
    String message = "Planets are formed from disc-shaped" +
            " cloud of gas and dust spinning around a newborn star.";

Earth class is extended from Planet class. Instead of displaying a generic info about planets, we can implement displayInfo() function again and display a specific information about planet Earth.

public class Earth extends Planet {
  public void displayInfo() {
    String message = "Earth is the third planet from the Sun.";

When we create an instance of Planet and call displayInfo() method, it will print generic message from superclass. If we create an instance of Instead of Earth, it will display overridden message for Earth.

Planet planet = new Planet();
Earth earth = new Earth();
planet.displayInfo();       // Planets are formed from disc-shaped...
earth.displayInfo();        // Earth is the third planet from...

10) What is the difference between Local variable and Instance variable?

Instance variables are defined in class level and they can be accessed from any method within the class.

Local variables are defined inside methods and they can only be accessed inside the method in which they are defined.

In the example below, var0 is an instance variable; var1, var2 are local variables. Since var0 is an instance variable, it can be used in both method1 and method2 methods. Local variable var1 can be used inside method1, but it cannot be accessed from method2. Line 13 gives a compilation error, because it’s trying to access var1 outside its scope.

public class VarScope {
  private int var0;

  public void method1() {
    int var1=0;
    System.out.println(var0);   // instance variable var0 can be accessed from all methods in the class
    System.out.println(var1);   // local variable var1 can only be accessed inside method1

  public void method2() {
    int var2=0;
    System.out.println(var1);   // Compile Error

11) What is the difference between Instance variable and Class variable?

Class variables are similar to Instance variables, they are defined in class level. The only difference is class variables are declared as static. Declaring a variable as static means, Java keeps only one copy of this variable in memory.

Each instance created from VarScope2 class will have its own copy of var1 instance variable, but they will share one copy of var2 class variable.

public class VarScope2 {
  int var1;
  static int var2;

  public VarScope2(int var1) {
    this.var1 = var1;

Let’s create 2 instances from VarScope2 class. For inst1, we are updating var2 class variable as 150, then we are updating var2 as 200 for inst2 instance. The output shows that var2 is updated as 200 for inst1 as well.

VarScope2 inst1 = new VarScope2(10);
inst1.var2 = 150;

VarScope2 inst2 = new VarScope2(20);
inst1.var2 = 200;

System.out.println("inst1.var1=" + inst1.var1 + ", inst1.var2=" + inst1.var2);
// inst1.var1=10, inst1.var2=200

System.out.println("inst2.var1=" + inst2.var1 + ", inst2.var2=" + inst2.var2);
// inst2.var1=20, inst2.var2=200

12) What are the access modifiers in Java?

You can restrict the scope of your class members using access modifiers. There are 4 access modifiers in Java: private, default, protected and public. The most restrictive access modifier is private and the least restrictive is public.

private: You can access private members (variables or methods) only from the class in which they are defined.
default: If you don’t use private, protected or public modifiers when declaring a member, then it has default access. Default access is less restrictive than private access. You can access members with default access from the class in which they are defined and you can also access these members from other classes in the same package.
protected: Protected members of a class can be accessed inside the class or other classes in the same package like default access. Protected members can also be accessed from subclasses.
public: This is the least restrictive access modifier. You can access these members from anywhere (even from classes inside other packages).

For a good software design you should prefer the most restrictive access level possible.

public class Access {
  private int var1;    // can be accessed only from Access class
  int var2;            // can be accessed Access class and other classes in the same package
  protected int var3;  // can be accessed Access class, other classes in the same package and all subclasses of Access
  public int var4;     // can be accessed from anywhere

12) Why do you use packages?

Packages are used to group related classes together. You might have hundreds of classes in a project. If you don’t organize classes into packages, it will become more difficult to maintain after a while.

You can think of packages as folders in the file system. Actually, what Java does when you create a package is to create the same folder structure in the file system.

13) What is the difference between Classes and Objects?

Classes can be thought of as blueprints or templates for objects. They contain class/instance variables and method implementations. Class is just a specification, it describes what will be stored as variables (state info) and defines how you can modify these variables (method implementations).

// A Sample Class
public class SampleClass {
  public void printHello() {
    System.out.println("Hello Java!");

When you create an instance (using new keyword), an object is created in runtime. Until you create an object, no space will be allocated in memory.

// An Object is created from SampleClass
public class ObjectCreator {
  public static void main(String[] args) {
    SampleClass object = new SampleClass();

14) What is the purpose of Garbage Collector?

In languages like C++, you have to manage memory yourself. When you are done with an object in C++, you have to deallocate the memory occupied by the object. If you forget to deallocate the memory, there can be memory leak problems.

In Java, thanks to garbage collection, you don’t have to deallocate unused objects. Garbage collector finds unused objects and reclaims the unused memory automatically.

15) Why do you need static methods?

You can use static methods without creating an object. A static method belongs to a class rather than a specific instance of a class.

If you are creating a method to update state information, you need to use non-static methods. For instance, customer number, customer name are state information for Customer class. Because each customer instance is unique and these instances will have unique customers numbers (or customer names).

// Example for non-static methods
public class Customer {
  private long customerNumber;
  private String name;

  public void setCustomerNumber(long customerNumber) {
    this.customerNumber = customerNumber;

  public void setName(String name) { = name;

If you will not change a state information (instances variables will not be updated), you can use static methods. Static methods are commonly used in Utility/Helper classes.

For instance, consider the class below. MathUtils class doesn’t contain any state variable (instance variable). It has one static method called sum(). This method double arguments and returns the sum of these numbers.

// Example for static methods
public class MathUtils {
  public static double sum(double... numbers) {
    double sum = 0;
    for (double number : numbers) {
      sum += number;
    return sum;

We don’t need to create an object instance for utility classes. You can directly call a static method using class name and method name. Since an instance isn’t created, memory is used effectively.

double sum = MathUtils.sum(5, 10, 15);