StackTips
Java

Most Popular Java Interview Questions and Answers

A comprehensive list of the most important and commonly asked Java interview questions and answers with detailed explanations.

What is the difference between comparison done by equals method and == operator?

In Java, equals() method is used to compare the contents of two string objects and returns true if the two have same value while == operator compares the references of two string objects.

In the following example, equals() returns true as the two string objects have same values. However == operator returns false as both string objects are referencing to different objects:

public class EqualsTest {

    public static void main(String args[]) {
        String str1 = new String("Hello World");
        String str2 = new String("Hello World");

      	//Reference comparison
      	System.out.println(s1 == s2);
      
      	//Content comparison
      	System.out.println(s1.equals(s2));
      
      	// integer-type
      	System.out.println(10 == 10);
      
      	// char-type
      	System.out.println('a' == 'a');
    }

}

Output

false
true
true
true

How is an infinite loop declared in Java?

Infinite loops are those loops that run infinitely without any breaking conditions. Some examples of consciously declaring infinite loop is:

Using For Loop:
for (;;)
{
   // Business logic
   // Any break logic
}
Using while loop:
while(true){
   // Business logic
   // Any break logic
}
Using do-while loop:
do{
   // Business logic
   // Any break logic
} while(true);

Why is the main method static in Java?

The main method is always static because static members are those methods that belong to the classes, not to an individual object. So if the main method will not be static then for every object, It is available. And that is not acceptable by JVM. JVM calls the main method based on the class name itself. Not by creating the object.

Because there must be only 1 main method in the java program as the execution starts from the main method. So for this reason the main method is static.

How would you differentiate between a String, StringBuffer, and a StringBuilder?

Storage area: In string, the String pool serves as the storage area. For StringBuilder and StringBuffer, heap memory is the storage area.

Mutability: A String is immutable, whereas both the StringBuilder and StringBuffer are mutable.

Efficiency: It is quite slow to work with a String. However, StringBuilder is the fastest in performing operations. The speed of a StringBuffer is more than a String and less than a StringBuilder. (For example appending a character is fastest in StringBuilder and very slow in String because a new memory is required for the new String with appended character.)

Thread-safty: In the case of a threaded environment, StringBuilder and StringBuffer are used whereas a String is not used. However, StringBuilder is suitable for an environment with a single thread, and a StringBuffer is suitable for multiple threads.

Syntax:

// String
String first = "InterviewBit";
String second = new String("InterviewBit");

// StringBuffer
StringBuffer third = new StringBuffer("InterviewBit");

// StringBuilder
StringBuilder fourth = new StringBuilder("InterviewBit");

What is a Comparator in java?

Consider the example where we have an ArrayList of employees like( EId, Ename, Salary), etc. Now if we want to sort this list of employees based on the names of employees. Then that is not possible to sort using the Collections.sort() method. We need to provide something to the sort() function depending on what values we have to perform sorting. Then in that case a comparator is used.

Comparator is the interface in java that contains the compare method. And by overloading the compare method, we can define that on what basis we need to compare the values.

What makes a HashSet different from a TreeSet?

Although both HashSet and TreeSet are not synchronized and ensure that duplicates are not present, there are certain properties that distinguish a HashSet from a TreeSet.

Implementation: For a HashSet, the hash table is utilized for storing the elements in an unordered manner. However, TreeSet makes use of the red-black tree to store the elements in a sorted manner.

Complexity/ Performance: For adding, retrieving, and deleting elements, the time amortized complexity is O(1) for a HashSet. The time complexity for performing the same operations is a bit higher for TreeSet and is equal to O(log n). Overall, the performance of HashSet is faster in comparison to TreeSet.

Methods: hashCode() and equals() are the methods utilized by HashSet for making comparisons between the objects. Conversely, compareTo() and compare() methods are utilized by TreeSet to facilitate object comparisons.

Objects type: Heterogeneous and null objects can be stored with the help of HashSet. In the case of a TreeSet, runtime exception occurs while inserting heterogeneous objects or null objects.

What are the differences between HashMap and HashTable in Java?

HashMapHashTable
HashMap is not synchronized thereby making it better for non-threaded applications.HashTable is synchronized and hence it is suitable for threaded applications.
Allows only one null key but any number of null in the values.This does not allow null in both keys or values.
Supports order of insertion by making use of its subclass LinkedHashMap.Order of insertion is not guaranteed in HashTable.

What are the different ways to create threads in Java?

We can define and implement a thread in java using two ways: Extending the Thread class

class ThreadExample extends Thread {  
   public void run(){  
       System.out.println("Thread runs...");  
   }  
   public static void main(String args[]){  
       ThreadExample ib = new ThreadExample();  
       ib.start();  
   }  
}

Implementing the Runnable interface

class ThreadExample implements Runnable {  
   public void run(){  
       System.out.println("Thread runs...");  
   }  
   public static void main(String args[]){  
       Thread ib = new Thread(new ThreadExample()); 
       ib.start();  
   }  
}

Implementing a thread using the method of Runnable interface is more preferred and advantageous as Java does not have support for multiple inheritances of classes. start() method is used for creating a separate call stack for the thread execution. Once the call stack is created, JVM calls the run() method for executing the thread in that call stack.

What is difference between thread and process?

A thread is a class in java that belongs to java.lang package. A thread is an lightweight process and has its own call stack. In Java, you can run multiple threads parallely. A thread is used to perform long running jobs dedicated without disturbing to the other part of program. Even if you don't create any new threads in your program, there is at least one thread i.e. main thread() which runs the application.

  1. Threads share the address space of the process that created it; processes have their own address.
  2. Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.
  3. Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes.
  4. Threads have almost no overhead; processes have considerable overhead.
  5. New threads are easily created; new processes require duplication of the parent process.
  6. Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes.
  7. Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process do not affect child processes.

What are the different states of a thread's life cycle?

  1. New - When a thread is instantiated it is in New state until the start() method is called on the thread instance. In this state the thread is not considered to be alive.
  2. Runnable - The thread enters into this state after the start method is called in the thread instance. The thread may enter into the Runnable state from Running state. In this state the thread is considered to be alive.
  3. Running - When the thread scheduler picks up the thread from the Runnable thread's pool, the thread starts running and the thread is said to be in Running state.
  4. Waiting/Blocked/Sleeping - In these states the thread is said to be alive but not runnable. The thread switches to this state because of reasons like wait method called or sleep method has been called on the running thread or thread might be waiting for some i/o resource so blocked. Dead - When the thread finishes its execution i.e. the run() method execution completes, it is said to be in dead state. A dead state can not be started again. If a start() method is invoked on a dead thread a runtime exception will occur.

What are different ways in which a thread can enter the waiting state?

A thread can enter the waiting state by the following ways:

  1. Invoking its sleep() method,
  2. By blocking on I/O
  3. By unsuccessfully attempting to acquire an object's lock
  4. By invoking an object's wait() method.
  5. It can also enter the waiting state by invoking its (deprecated) suspend() method.

What is the difference between yield and sleep?

When a task invokes its yield() method, it returns to the ready state, either from waiting, running or after its creation. When a task invokes its sleep() method, it returns to the waiting state from a running state.

Extending Thread class or implementing Runnable Interface. Which is better?

You have two ways to create a thread in Java. First, making your class "extends" Thread class. The other way is making your class implement "Runnable" interface.

The latter is more advantageous, cause when you are going for multiple inheritance, then only interface can help. If you are already inheriting a different class, then you have to go for Runnable Interface. Also, if you are implementing interface, it means you have to implement all methods in the interface.

Both Thread class and Runnable interface are provided for convenience and use them as per the requirement. But if you are not extending any class, better extend Thread class as it will save few lines of coding. Otherwise performance wise, there is no distinguishable difference. A thread is in the ready state after it has been created and started.

What is mutual exclusion? How can you take care of mutual exclusion using Java threads?

Mutual exclusion in Java is a mechanism that allows only one thread to access a shared resource or critical section of code at a time, preventing race conditions where multiple threads can access and modify the same resource simultaneously.

For mutual exclusion, you can simply use the synchronized keyword, which can be applied to a method or a block of code to ensure that only one thread can access the synchronized code at a time.

Java offers different options to achieve mutual exclusion, such as the Semaphore class, the ReadWriteLock interface, the AtomicInteger class, and the StampedLock class. The choice of implementation depends on the specific requirements and constraints of the application.

  1. Semaphore: The Semaphore class can be used to implement mutual exclusion. It allows a limited number of threads to access a critical section at the same time.
  2. ReadWriteLock: The ReadWriteLock interface can be used to implement mutual exclusion for read and write operations. It allows multiple threads to read a shared resource simultaneously, but only one thread can write to the resource at a time.
  3. AtomicInteger: The AtomicInteger class can be used to implement mutual exclusion for integer values. It provides atomic operations such as incrementAndGet() and decrementAndGet(), which ensures that only one thread can modify the value at a time.
  4. StampedLock: The StampedLock class can be used to implement mutual exclusion for read and write operations. It provides optimistic read locks, which allows multiple threads to read a shared resource simultaneously, and a write lock, which allows only one thread to write to the resource at a time.

What is the difference between preemptive scheduling and time slicing?

Under preemptive scheduling, the highest priority task executes until it enters the waiting or dead states or a higher priority task comes into existence. Under time slicing, a task executes for a predefined slice of time and then re-enters the pool of ready tasks. The scheduler then determines which task should execute next, based on priority and other factors.

What is deadlock?

When two threads are waiting for each other and can't proceed until the first thread obtains a lock on the other thread or vice versa, the program is said to be in a deadlock.

What are synchronized methods and synchronized statements?

Synchronized methods are methods that are used to control access to an object. A thread only executes a synchronized method after it has acquired the lock for the method's object or class. Synchronized statements are similar to synchronized methods. A synchronized statement can only be executed after a thread has acquired the lock for the object or class referenced in the synchronized statement.

What is a volatile keyword?

In general, each thread has its own copy of the variable, such that one thread is not concerned with the value of the same variable in the other thread. But sometime this may not be the case. Consider a scenario in which the count variable is holding the number of times a method is called for a given class irrespective of any thread calling, in this case, irrespective of thread access the count has to be increased so the count variable is declared as volatile.

The copy of the volatile variable is stored in the main memory, so every time a thread access the variable even for reading purpose the local copy is updated each time from the main memory. The volatile variable also has performance issues.

What is Serializable?

Serializable is a marker interface. When an object has to be transferred over a network ( typically through RMI or EJB) or persists the state of an object to a file, the object Class needs to implement a Serializable interface. Implementing this interface will allow the object converted into a byte stream and transfer over a network.

What is use of serialVersionUID?

During object serialization, the default Java serialization mechanism writes the metadata about the object, which includes the class name, field names, types, and superclass. This class definition is stored as a part of the serialized object. This stored metadata enables the deserialization process to reconstitute the objects and map the stream data into the class attributes with the appropriate type every time an object is serialized the java serialization mechanism automatically computes a hash value.

ObjectStreamClass’s computeSerialVersionUID() method passes the class name, sorted member names, modifiers, and interfaces to the secure hash algorithm (SHA), which returns a hash value. The serialVersionUID is also called suid.

So when the serialized object is retrieved, the JVM first evaluates the suid of the serialized class and compares the suid value with the one of the objects. If the suid values match then the object is said to be compatible with the class and hence it is de-serialized. If not InvalidClassException exception is thrown.

Changes to a serializable class can be compatible or incompatible.

What is difference between ArrayList and Vector?

  • Synchronization – ArrayList is not thread-safe whereas Vector is thread-safe. In Vector class each method like add()get(int i) is surrounded with a synchronized block and thus making Vector class thread-safe.
  • Data growth – Internally, both the ArrayList and Vector hold onto their contents using an Array. When an element is inserted into an ArrayList or a Vector, the object will need to expand its internal array if it runs out of room. A Vector defaults to doubling the size of its array, while the ArrayList increases its array size by 50 percent.

What is difference between HashMap and HashTable?

Both collections implement Map. Both collections store value as key-value pairs. The key differences between the two are

    1. Hashmap is not synchronized in nature but HashTable is.
    2. Another difference is that the iterator in the HashMap is fail-safe while the enumerator for the HashTable isn’t. Fail-safe – if the HashTable is structurally modified at any time after the iterator is created, in any way except through the iterator’s own remove method, the iterator will throw a ConcurrentModificationException
    3. HashMap permits null values and only one null key, while Hashtable doesn’t allow key or value as null.

When to use ArrayList or LinkedList?

  • For the ArrayList, doing random lookup using get() is fast, but for LinkedList, it’s slow. It’s slow because there’s no efficient way to index into the middle of a linked list.
  • When removing elements, using ArrayList is slow. This is because all remaining elements in the underlying array of Object instances must be shifted down for each remove operation. But here LinkedList is fast because deletion can be done simply by changing a couple of links.
  • So an ArrayList works best for cases where you’re doing random access on the list, and a LinkedList works better if you’re doing a lot of editing in the middle of the list.

What is final, finalize() and finally? What does it mean that a class or member is final?

  • final – Variables defined in an interface are implicitly final. A final class can’t be extended i.e., the final class may not be subclassed. This is done for security reasons with basic classes like String and Integer. It also allows the compiler to make some optimizations and makes thread safety a little easier to achieve. A final method can’t be overridden when its class is inherited. You can’t change the value of a final variable (which is a constant)
  • finally – a keyword used in exception handling will be executed whether or not an exception is thrown. For example, the closing of open connections is done in the final method.
  • finalize – helps in garbage collection. finalize() method is used just before an object is destroyed and garbage collected.

What is Method Overriding? What restrictions are placed on method overriding?

When a class defines a method using the same name, return type, and argument list as that of a method in its superclass, the method in the subclass is said to override the method present in the Superclass. When the method is invoked for an object of the class, it is the new definition of the method that is called and not the method definition from the superclass. Restrictions placed on method overriding

  • Overridden methods must have the same name, argument list, and return type.
  • The overriding method may not limit the access of the method it overrides. Methods may be overridden to be more public, not more private.
  • The overriding method may not throw any exceptions that may not be thrown by the overridden method.

What is the difference between an Inner Class and a Sub-Class?

An Inner class is a class that is nested within another class. An Inner class has access rights to the class which is nesting it and it can access all variables and methods defined in the outer class.

A sub-class is a class that inherits from another class called a super class. Sub-class can access all public and protected methods and fields of its super class.

What are the various access specifiers for Java classes?

In Java, access specifiers are the keywords used before a class name that defines the access scope. The types of access specifiers for classes are:

  • Public: Class, Method, Field is accessible from anywhere.
  • Protected: Method, Field can be accessed from the same class to which they belong or from the sub-classes, and from the class of the same package, but not from outside.
  • Default: Method, Field, and class can be accessed only from the same package and not from outside of its native package.
  • Private: Method, Field can be accessed from the same class to which they belong.

What?s the purpose of Static methods and static variables?

When there is a requirement to share a method or a variable between multiple objects of a class instead of creating separate copies for each object, we use static keywords to make a method or variable shared for all objects.

What is data encapsulation and what?s its significance?

Encapsulation is a concept in Object Oriented Programming for combining properties and methods in a single unit.

Encapsulation helps programmers to follow a modular approach for software development as each object has its own set of methods and variables and serves its functions independent of other objects. Encapsulation also serves the data hiding purpose.

What is a singleton class? Give a practical example of its usage.

Singleton design pattern belongs to the creational family of patterns that governs the instantiation process. This pattern ensures at most one instance of a particular class is ever created in your application. Examples such as:

  • Project Configuration: A class that reads your project configuration can be made Singleton. By making this singleton, you are allowing global access for all classes in your application. If the project configs are stored in a file, it just reads once and holds on the application cache. You don’t have to read the file multiple times.
  • Application Log: Logger will be used everywhere in your application. It must be initialized once and used everywhere.
  • Analytics and Reporting: If you are using some kind of data analysis tool like Google Analytics, you will notice that they are designed to be a singleton. It initializes once and is used everywhere for each user action.

Read more about singleton implementation here.

What is the difference between continue and break statement?

The break and continue are two important keywords used in the loops. When a break keyword is used in a loop, the loop is broken instantly while when the continue keyword is used, the current iteration is broken and the loop continues with the next iteration.

In the below example, Loop is broken when the counter reaches 4.

for (counter = 0; counter< 10; counter++)
    system.out.println(counter);

	if (counter == 4) {
	    break;
	}
}

In the below example when the counter reaches 4, the loop jumps to the next iteration and any statements after the continue keyword are skipped for the current iteration.

for (counter = 0; counter < 10; counter++)
    system.out.println(counter);
	if (counter == 4) {
    	continue;
	}
}

What is the difference between double and float variables in Java?

In java, float takes 4 bytes in memory while Double takes 8 bytes in memory. Float is single-precision floating-point decimal number while Double is a double-precision decimal number.

What is Final Keyword in Java?

A variable declared with the final keyword is a constant in java. Value can be assigned only once and after the assignment, the value of a constant can’t be changed.

For example, a constant with the name MAX_LIMIT is declared and assigned value:

private final int MAX_LIMIT=100

When a method is declared as final, it can NOT be overridden by the subclasses. This method is faster than any other method because they are resolved at the complied time.

When a class is declares as final, it cannot be inherited. Example String, Integer, and other wrapper classes.

Can we declare a class as Abstract without having any abstract method?

Yes, we can create an abstract class by using the abstract keywords before the class names even if it doesn’t have any abstract method. However, if a class has even one abstract method, it must be declared as abstract otherwise it will give an error.

What?s the difference between an Abstract Class and Interface in Java?

The primary difference between an abstract class and an interface is that an interface can only possess a declaration of public static methods with no concrete implementation while an abstract class can have members with any access specifiers (public, private, etc) with or without a concrete implementation.

Another key difference in the use of abstract classes and interfaces is that a class that implements an interface must implement all the methods of the interface while a class that inherits from an abstract class doesn’t require implementation of all the methods of its super class.

A class can implement multiple interfaces but it can extend only one abstract class.

Can we declare the main method of our class as private?

In java, the main method must be public static in order to run any application correctly. If the main method is declared as private, the developer won’t get any compilation error however, it will not get executed and will give a runtime error.

How we can execute any code even before main method?

If we want to execute any statements before even the creation of objects at the load time of class, we can use a static block of code in the class. Any statements inside this static block of code will get executed once at the time of loading the class even before the creation of objects in the main method.