Core Java basic interview Q&A

  1. Explain Java OOPS concepts
  2. Difference between method overloading and method overriding
  3. Internal working of Hashmap
  4. How to iterate Hashmap in Java?
  5. Difference between Hashmap and Treemap?
  6. Difference between Hashmap and Hashtable?
  7. Difference between Hashmap and Concurrent Hashmap?
  8. Difference between == and Equals()
  9. Why String is immutable?
  10. Type of Interfaces in Java
  11. What is Marker interface?
  12. What is the use of the keyword transient?
  13. Static method vs default method in Interface
  14. What is Serialization and Deserialization in Java?
  15. Explain Deadlock in Java?
  16. Explain String joiner
  17. How many ways can we create object of a class?
  18. How to prevent instantiation of a class
  19. Comparable vs Comparator in Java
  20. Life cycle of a thread?
  21. Difference between Vector and ArrayList
  22. Which is the form of threadsafe arraylist? Or you can say what is failfast, failsafe collection and can you name few of them?
  23. Explain Class loaders in Java
  24. Difference between Path and Classpath?
  25. What is Enum?

--------------------------------------------------------------------------------------------------------

Explain Java OOPS concepts

  1. Object

  2. Class

  3. Inheritance

  4. Polymorphism

  5. Abstraction

  6. Encapsulation


Object 

=> An Object can be defined as an instance of a class. 

=> An Object contains an address and takes up some space in memory.

=> Constructor is used to allocate memory for the object

Class

=> Collection of objects is called class. It is a logical entity. 

=> A class can also be defined as a blueprint from which you can create an individual object.

=> Class doesn't consume any space.

Inheritance

=> When one object acquires all the properties and behaviors of a parent object, it is known as inheritance. 

=> It provides code reusability. It is used to achieve runtime polymorphism.

Polymorphism

=> If one task is performed in different ways, it is known as polymorphism.

=> In Java, we use method overloading and method overriding to achieve polymorphism.

Abstraction

=> Hiding internal details and showing functionality is known as abstraction. For example phone call, we don't know the internal processing.

=> In Java, we use abstract class and interface to achieve abstraction.

Encapsulation

=> Binding (or wrapping) code and data together into a single unit are known as encapsulation.

=> A java class is the example of encapsulation.

    

Difference between Method overloading and Method overriding

Method overloading
Method overriding
Method overloading may or may not require inheritance.
Method overriding always needs inheritance.
In method overloading, methods must have the same name and different signatures
In method overriding, methods must have the same name and same signature.

 

Internal working of Hashmap?


What is HashMap

=> HashMap is a part of the Java collection framework. It uses a technique called Hashing.

=> HashMap is used whenever data is stored as key-value pairs where values can be added, retrieved and deleted using keys

What is Hashing

=> It is the process of converting an object into an integer value. The integer value helps in indexing and faster searches.

=> Before understanding the internal working of HashMap, you must be aware of hashCode() and equals() method.


equals():

It checks the equality of two objects.

It compares the Key, whether they are equal or not.

It is a method of the Object class. It can be overridden. If you override the equals() method, then it is mandatory to override the hashCode() method.


hashCode():

This is the method of the object class.

It returns the memory reference of the object in integer form.

The value received from the method is used as the bucket number.

The bucket number is the address of the element inside the map.

Hash code of null Key is 0.


 


Buckets: 

=> Array of the node is called buckets. 

=> Each node has a data structure like a LinkedList. 

=> More than one node can share the same bucket. It may be different in capacity.

 

 To insert Key-Value pair in Hashmap : 

    => We use method put() to insert Key-Value pair in Hashmap

    => Default size of Hashmap is 16 (0 to 15)

 

What is Hashing?

It is the process of converting an object into an integer value. The integer value helps in indexing and faster searches.

Before understanding the internal working of HashMap, you must be aware of hashCode() and equals() method. 

hashCode():

This is the method of the object class.

It returns the memory reference of the object in integer form.

equals():

It checks the equality of two objects.

It compares the Key, whether they are equal or not.

It is a method of the Object class. It can be overridden. If you override the equals() method, then it is mandatory to override the hashCode() method. 

 

How to iterate Hashmap in Java? 

There is a numerous number of ways to iterate over HashMap of which 5 are listed as below:

  1. Iterate through a HashMap Map.Entry EntrySet using Iterators.

  2. Iterate through HashMap KeySet using Iterator.

  3. Iterate HashMap using for-each loop.

  4. Iterating through a HashMap using Lambda Expressions.

  5. Loop through a HashMap using Stream API


Difference between HashMap and TreeMap?

HashMap

TreeMap

HashMap can contain one null key

TreeMap cannot contain any null key

HashMap maintains no order

TreeMap maintains ascending order

 

Difference between HashMap and HashTable?

HashMap
HashTable
Multiple threads can operate concurrently So, HashMap is not-thread safe
At a time, only one thread is allowed to operate So, HashTable is thread-safe
HashMap allows only one null key and multiple null values
HashTable does not allow any null key or value
HashMap is fast
HashTable is slow

 

Difference between HashMap and ConcurrentHashMap?



(Youtube video Credits to the creator)


Difference Between == and Equals() 

== Vs .equals()

Both are used to compare two objects in the java.

.equals() for content comparison

== checks if both objects point to same memory location 

 

Why String is immutable?

When we assign value to a String reference variable, the String object will be created inside the String Pool. 

If we assign another value to the same String reference variable, new String object will be created inside the String Pool, ie Existing String object will not be changed.

If we declare another one String reference variable with same string value, new String object will not be created and String reference variable in Stack memory will point to the existing String object value in the pool.

In short, String reference variables with same String value points to the same String object in the String pool instead of creating separate String object in the pool. Thats why we say String is immutable. This design pattern is called as Fly weight pattern.

If we create a String using the keyword new with the same String value, then it will create an object inside the heap memory but still points to the same String object in the String pool.


 

 For more understanding :

 

(Credits to Navin Reddy (www.telusko.com))

 

How to make String mutable : 

    We can make String mutable by using StringBuffer and StringBuilder.


Types of Interface in Java :

 

01. Normal Interface

02. Marker Interface

03. Functional or SAM(Single Abstract Method) Interface


01. Normal Interface

=> Interface which contains one or more abstract methods

02.  Marker Interface

An Interface with no method is called as Marker Interface

Example for Predefined Marker Interfaces are Interface Serializable, Interface Cloneable

03. Functional or SAM(Single Abstract Method) Interface

SAM - Single Abstract Method Interface

An Interface that contains exactly one abstract method is known as Functional Interface.

    => Introduced in Java 8 

    => Functional Interface can have any number of default and static methods but can contain only one abstract method

    => It can also declare methods of Object class  

Example for Predefined Functional Interface : Java.Lang.Runnable

Functional Interface vs Normal Interface 

=> Functional Interface can have only one abstract method whereas normal Interface can have multiple number of abstract methods.

What is Marker Interface :

An Interface with no method is called as Marker Interface

Example for Predefined Marker Interfaces are Interface Serializable, Interface Cloneable
 

What is Serialization and Deserialization in Java ?

Serialization 

=> Serialization is the process of converting an object into binary form at which can be persisted in the desk or sent over the network to any other running JVM
 
=> How to make a class Serializable?
            By implementing the Interface Serializable
 
=> Interface Serializable is available in Java.io.package
 
Deserialization
=> Creating an object from binary stream is called Deserialization
 
What is the use of keyword transient : 

=> If we do not want any field to be part of object, then we declare it as either static or transient

=>The keyword transient can be used with the data members of the class in order to exclude it from serialization

=>If the class or its hierarchy does not extend the Interface Serializable, then transient does not make any sense.

static method vs default method in Interface : 

static method in Java Interface

default method in Java Interface

Cannot override the static method of Interface

Can override the default method of Interface

static methods can be invoked using the name of the Interface

default methods can be invoked using the object of implementation class

 

Explain Deadlock in Java

 

 

=> Deadlock in Java occurs when two or more threads
are blocked forever, each waiting for a resource that
another thread holds, creating a circular dependency. 

=> This results in a situation where none of the
threads can proceed, causing the program to hang.

 

Example of Deadlock in Java 

public class DeadlockExample {

    public static void main(String[] args) {

        String resource1 = "Resource1";

        String resource2 = "Resource2";


        // Thread 1

        Thread t1 = new Thread(() -> {

            synchronized (resource1) {

                System.out.println("Thread 1: Locked resource1");

                try { Thread.sleep(100); } catch (Exception e) {}

                synchronized (resource2) {

                    System.out.println("Thread 1: Locked resource2");

                }

            }

        });


        // Thread 2

        Thread t2 = new Thread(() -> {

            synchronized (resource2) {

                System.out.println("Thread 2: Locked resource2");

                try { Thread.sleep(100); } catch (Exception e) {}

                synchronized (resource1) {

                    System.out.println("Thread 2: Locked resource1");

                }

            }

        });


        t1.start();

        t2.start();

    }

}

 

Explanation of the Example

Thread 1 locks resource1 and waits to lock resource2.

Thread 2 locks resource2 and waits to lock resource1.

Both threads are now waiting for each other to release
their respective resources, causing a deadlock.

The program will hang because neither thread can proceed.


How to avoid Deadlocks ?

=> Avoid nested locks as much as possible

=> Lock Ordering : Enforce a global ordering for acquiring
the locks.
For example, always acquire locks in alphabetical order 

=> Timeouts : Use tryLock() which allows the thread to
backoff if the lock is not acquired. 

=> Avoid Hold and Wait : Ensure the thread either acquires
all the resources at once or releases the resources before
waiting for others 

=> Use java.util.concurrent classes like ExecutorService


How to detect Deadlocks ?

=> Use tools like jstack, VisualVM or JConsole

=> Use ThreadMXBean class to find deadlocked threads 




import java.lang.management.*;


public class DeadlockDetector {

    public static void main(String[] args) {

        ThreadMXBean bean = 

            ManagementFactory.getThreadMXBean();

        long[] deadlockedThreads = 

            bean.findDeadlockedThreads();

        if (deadlockedThreads != null) {

            System.out.println("Deadlock detected!");

        }

    }

}

 

Explain String Joiner

=> String Joiner Class introduced in Java 8
=> String Joiner Class provides efficient way to concatenate
multiple Strings with a defined delimiter (character),
optional prefix and suffix


Example :
import java.util.StringJoiner;

public class StringJoinerExample {
public static void main(String[] args) {
// Create a StringJoiner with comma and space as delimiter
StringJoiner sj1 = new StringJoiner(", ");
sj1.add("Apple");
sj1.add("Banana");
sj1.add("Cherry");
System.out.println("Joined String 1: " + sj1.toString()); 

// Output: Apple, Banana, Cherry

// Create a StringJoiner with a prefix, suffix, and delimiter
StringJoiner sj2 = new StringJoiner(" - ", "[", "]");
sj2.add("Red");
sj2.add("Green");
sj2.add("Blue");
System.out.println("Joined String 2: " + sj2.toString()); 

// Output: [Red - Green - Blue]

// Demonstrate merging
StringJoiner sj3 = new StringJoiner(" | ");
sj3.add("One");
sj3.add("Two");

sj1.merge(sj3); // Merges sj3 into sj1
System.out.println("Merged String: " + sj1.toString()); 

// Output: Apple, Banana, Cherry, One | Two
}
}

 

How many ways can we create an Object of a class ?

 

=> Using the new keyword 

ClassName obj = new ClassName();


=> Using newInstance() and Class.forName();

Class<?> cls = Class.forName("ClassName");

Object obj = cls.newInstance(); // Calls default constructor

  

=> Using newInstance() and class.getConsructor()

Constructor<ClassName> constructor = ClassName.class.getConstructor();

ClassName obj = constructor.newInstance();


=> Using createInstance() factory method 

ClassName obj = ClassName.createInstance(); // Example factory method


=> Using Object cloning - obj1.clone()

If class implements Cloneable interface, we can create copy of an
existing object using clone() method 

ClassName obj1 = new ClassName();

ClassName obj2 = (ClassName) obj1.clone();


=> Using Deserialization - If an Object is serialized (Save in a file or stream),
we can recreate it by deserializing it - inputStream.readObject()

ObjectInputStream in = new ObjectInputStream(new FileInputStream("file.ser"));

ClassName obj = (ClassName) in.readObject();

  

How to prevent instantiation of a class ?

=> Abstract Class : Make a class Abstract. Abstract class cannot be instantiated directly 
=> Private Constructor
=> Throw an exception in the constructor to explicitly prevent 
=> Singleton Pattern : Combine private constructor with a static method to 
access the instance. Only one instance is allowed  

Comparable vs Comparator in Java ?

Java provides two interfaces to sort objects using data members of the class: 

    1. Comparable

    2. Comparator

Comparable

Comparator

1) Comparable provides a single sorting sequence.

In other words, we can sort the collection on the basis of a single element such as id, name, and price.

The Comparator provides multiple sorting sequences.

In other words, we can sort the collection on the basis of multiple elements such as id, name, and price etc.

2) Comparable affects the original class, i.e., the actual class is modified.

Comparator doesn't affect the original class, i.e., the actual class is not modified.

3) Comparable provides compareTo() method to sort elements.

Comparator provides compare() method to sort elements.

4) Comparable is present in the java.lang package.

A Comparator is present in the java.util package.

5) We can sort the list elements of Comparable type by Collections.sort(List) method.

We can sort the list elements of Comparator type by Collections.sort(List, Comparator) method.

 

Life cycle of Thread


c2c : https://www.javatpoint.com/life-cycle-of-a-thread

 
In Java, a thread always exists in any one of the following states. These states are:

    1. New 

    2. Active 

    3. Blocked / Waiting 

    4. Timed Waiting 

    5. Terminated 


New: Whenever a new thread is created, it is always in the new state. For a thread in the new state, the code has not been run yet and thus has not begun its execution. 


Active: When a thread invokes the start() method, it moves from the new state to the active state. The active state contains two states within it: one is runnable, and the other is running. 


Runnable: A thread, that is ready to run is then moved to the runnable state. In the runnable state, the thread may be running or may be ready to run at any given instant of time. It is the duty of the thread scheduler to provide the thread time to run, i.e., moving the thread the running state.

A program implementing multithreading acquires a fixed slice of time to each individual thread. Each and every thread runs for a short span of time and when that allocated time slice is over, the thread voluntarily gives up the CPU to the other thread, so that the other threads can also run for their slice of time. Whenever such a scenario occurs, all those threads that are willing to run, waiting for their turn to run, lie in the runnable state. In the runnable state, there is a queue where the threads lie. 



Running: When the thread gets the CPU, it moves from the runnable to the running state. Generally, the most common change in the state of a thread is from runnable to running and again back to runnable. 


Blocked or Waiting: Whenever a thread is inactive for a span of time (not permanently) then, either the thread is in the blocked state or is in the waiting state. 


For example, a thread (let's say its name is A) may want to print some data from the printer. However, at the same time, the other thread (let's say its name is B) is using the printer to print some data. Therefore, thread A has to wait for thread B to use the printer. Thus, thread A is in the blocked state. A thread in the blocked state is unable to perform any execution and thus never consume any cycle of the Central Processing Unit (CPU). Hence, we can say that thread A remains idle until the thread scheduler reactivates thread A, which is in the waiting or blocked state.

When the main thread invokes the join() method then, it is said that the main thread is in the waiting state. The main thread then waits for the child threads to complete their tasks. When the child threads complete their job, a notification is sent to the main thread, which again moves the thread from waiting to the active state.

If there are a lot of threads in the waiting or blocked state, then it is the duty of the thread scheduler to determine which thread to choose and which one to reject, and the chosen thread is then given the opportunity to run.


Timed Waiting: Sometimes, waiting for leads to starvation. For example, a thread (its name is A) has entered the critical section of a code and is not willing to leave that critical section. In such a scenario, another thread (its name is B) has to wait forever, which leads to starvation. To avoid such scenario, a timed waiting state is given to thread B. Thus, thread lies in the waiting state for a specific span of time, and not forever. A real example of timed waiting is when we invoke the sleep() method on a specific thread. The sleep() method puts the thread in the timed wait state. After the time runs out, the thread wakes up and start its execution from when it has left earlier. 


Terminated: A thread reaches the termination state because of the following reasons:

    • When a thread has finished its job, then it exists or terminates normally. 

    • Abnormal termination: It occurs when some unusual events such as an unhandled exception or segmentation fault. 

A terminated thread means the thread is no more in the system. In other words, the thread is dead, and there is no way one can respawn (active after kill) the dead thread.

 

Difference between Vector and ArrayList  

For reference :

Vector

ArrayList

Package java.util

Package java.util

Introduced in Java 1.0, later updated with List Collection framework (1.2)

Introduced in Java 1.2, Part of Collection Framework

Thread-safe (Synchronized methods)

Not Thread-safe

Slower due to Synchronized methods

Faster due to no synchronization

Increases the capacity by 100% when the limit exceeds

Increases the capacity by 50% when the limit exceeds

Default capacity 10 elements

Default capacity 10 elements

ArrayList is better than Vector in almost all the cases as the ArrayList is superior than Vector

ArrayList is better than Vector in almost all the cases


Which is the form of thread-safe arraylist? Or you can say what is failfast, failsafe collection and can you name a few of them?

Which is the form of thread-safe arraylist ?

 

=> An ArrayList is not thread safe by default but we can make it thread-safe and synchronized by using

1. Collections.synchronizedList() - method returns synchronized list

2. CopyOnWriteArrayList class - Thread safe variant of ArrayList 

 

 

 

 What are fail-fast, fail-safe collections ?

=> In Java, fail-fast and fail-safe collections refer to
how collections handle modification (like adding,
removing, updating elements) during iteration.

FAIL-FAST COLLECTION

FAIL-SAFE-COLLECTION

Fail-fast collections detect structural modifications (eg. adding, removing elements) during iteration and immediately throw a concurrentModificationException to prevent unpredictable behavior  

Fail-safe collections allow modification during iteration without throwing exceptions. They typically work on a copy of the collection or designed to handle concurrent modification safely 

They use an internal counter (eg. modcount) to track modifications.

If the counter changes during iteration, the iterator fails fast by throwing an exception

They either create copy of the collection at the start of the iteration (eg. CopyOnWriteArrayList) or use concurrent mechanisms (eg. concurrentHashMap) to avoid conflicts 

Single threaded environment

Multi-threaded environments where the concurrent modifications are expected

If we want to use, we need to ensure no concurrent modifications occur during iteration

Performance overhead due to copying


ArrayList, LinkedList,
HashMap, HashSet,
TreeMap, TreeSet

CopyOnWriteArrayList, ConcurrentHashMap

Explain Class Loaders in Java

=> Class loaders are required to load .class file into memory.

Three types of class loader :
    1. Bootstrap class loader
    2. Extensions class loader 
    3. System class loader 


Difference between Path and ClassPath ?

PATH

CLASS PATH

Represents a file or directory path in the file system

Specifies locations where JVM looks for classes and resources

What is Enum ?

=> Enum is a special data type used to define a fixed set of constants, providing type-safe and self documenting code. 

=> It is defined by using the keyword enum. It can include fields, constructors, methods. 
Example : enum Day { MONDAY, TUESDAY, WEDNESDAY }