Core JAVA

1. What is difference between Heap and Stack Memory in java?

Java Heap Space:

Java Heap space is used by java runtime to allocate memory to Objects and JRE classes. Whenever we create any object, it’s always created in the Heap space.

Garbage Collection runs on the heap memory to free the memory used by objects that doesn’t have any reference. Any object created in the heap space has global access and can be referenced from anywhere of the application.

Java Stack Memory:

Stack in java is a section of memory which contains methods, local variables and reference variables. Local variables are created in the stack.

Stack memory is always referenced in LIFO (Last-In-First-Out) order. Whenever a method is invoked, a new block is created in the stack memory for the method to hold local primitive values and reference to other objects in the method.

As soon as method ends, the block becomes unused and become available for next method. Stack memory size is very less compared to Heap memory.

Difference

ParameterStack MemoryHeap Space
ApplicationStack is used in parts, one at a time during execution of a threadThe entire application uses Heap space during runtime
SizeStack has size limits depending upon OS and is usually smaller then HeapThere is no size limit on Heap
StorageStores only primitive variables and references to objects that are created in Heap SpaceAll the newly created objects are stored here
OrderIt is accessed using Last-in First-out (LIFO) memory allocation systemThis memory is accessed via complex memory management techniques that include Young Generation, Old or Tenured Generation, and Permanent Generation.
LifeStack memory only exists as long as the current method is runningHeap space exists as long as the application runs
EfficiencyComparatively much faster to allocate when compared to heapSlower to allocate when compared to stack
Allocation/DeallocationThis Memory is automatically allocated and deallocated when a method is called and returned respectivelyHeap space is allocated when new objects are created and deallocated by Gargabe Collector when they are no longer referenced

2. What is the difference between factory and abstract factory pattern?

The Factory Method is usually categorized by a switch statement where each case returns a different class, using the same root interface so that the calling code never needs to make decisions about the implementation.

For example credit card validator factory which returns a different validator for each card type.

public ICardValidator GetCardValidator (string cardType)
{
    switch (cardType.ToLower())
    {
        case "visa":
            return new VisaCardValidator();
        case "mastercard":
        case "ecmc":
            return new MastercardValidator();
        default:
            throw new CreditCardTypeException("Do not recognise this type");
    }
}

Abstract Factory patterns work around a super-factory which creates other factories. This factory is also called as factory of factories. This type of design pattern comes under creational pattern as this pattern provides one of the best ways to create an object.

In Abstract Factory pattern an interface is responsible for creating a factory of related objects without explicitly specifying their classes. Each generated factory can give the objects as per the Factory pattern.

3. What is the difference between transient and volatile variable in Java?

Note

Serialization in Java is the process of converting an object into a byte stream, which can then be easily saved to a file, transmitted over a network, or stored in a database. This byte stream is platform-independent, meaning it can be deserialized (converted back into an object) on a different machine or JVM.

Transient Keyword:
  1. Purpose: It is used in serialization to mark a member variable that should not be serialized. If a variable is marked as transient, it will not be saved during serialization, and its value will be reset to the default when the object is deserialized.
  2. Usage: Typically used when you do not want to save sensitive information like passwords, or when a variable’s value can be derived or reconstructed after deserialization.
  3. 👇🏼 Effect: When an object of User class is serialized, the password field will not be included, and during deserialization, its value will be null.
class User implements Serializable {
    private String username;
    private transient String password; // This will not be serialized
 
    // Constructor, getters, setters
}
Volatile Keyword:
  1. Purpose: It is used to ensure that multiple threads correctly handle a variable. The volatile keyword indicates that a variable’s value will be read from and written to the main memory, not from the thread’s local cache. This is crucial in a multithreaded environment where multiple threads might be modifying the same variable.
  2. Usage: Typically used for flags or states that are accessed by multiple threads concurrently.
  3. 👇🏼 Effect: When a thread updates the value of flag, other threads reading it will see the updated value immediately, instead of an old cached value.
public class SharedData {
    private volatile boolean flag = false;
 
    public void changeFlag() {
        flag = true;
    }
 
    public boolean getFlag() {
        return flag;
    }
}

4. What will be the initial value of an object reference which is defined as an instance variable?

The object references are all initialized to null in Java. However in order to do anything useful with these references, It must set to a valid object, else you will get NullPointerExceptions everywhere you try to use such default initialized references.

5. What’s constructor chaining?

Constructor chaining is the process of calling one constructor from another constructor within the same class or from a subclass constructor using the this() or super() keyword. This concept ensures that when an object is created, all constructors in the inheritance chain are executed in a specific order, initializing the instance properly.

Types of Constructor Chaining:
  1. Within the Same Class (this()):
public class Car {
    private String model;
    private int year;
 
    // Constructor with no arguments
    public Car() {
        this("Unknown Model", 2023); // Calling another constructor in the same class
    }
 
    // Constructor with one argument
    public Car(String model) {
        this(model, 2023); // Chaining to the constructor with two arguments
    }
 
    // Constructor with two arguments
    public Car(String model, int year) {
        this.model = model;
        this.year = year;
    }
 
    public void display() {
        System.out.println("Car Model: " + model + ", Year: " + year);
    }
 
    public static void main(String[] args) {
        Car car1 = new Car();
        car1.display(); // Output: Car Model: Unknown Model, Year: 2023
 
        Car car2 = new Car("Tesla");
        car2.display(); // Output: Car Model: Tesla, Year: 2023
 
        Car car3 = new Car("BMW", 2021);
        car3.display(); // Output: Car Model: BMW, Year: 2021
    }
}
  1. Between Superclass and Subclass (super()):
// Superclass
public class Vehicle {
    private int speed;
 
    public Vehicle() {
        this(0); // Calls the constructor with arguments
        System.out.println("Vehicle no-arg constructor called");
    }
 
    public Vehicle(int speed) {
        this.speed = speed;
        System.out.println("Vehicle constructor with speed: " + speed);
    }
}
 
// Subclass
public class Bike extends Vehicle {
    private String brand;
 
    public Bike() {
        this("Default Brand"); // Calls the constructor with a String argument in the same class
        System.out.println("Bike no-arg constructor called");
    }
 
    public Bike(String brand) {
        super(50); // Calls the constructor of the superclass with an integer argument
        this.brand = brand;
        System.out.println("Bike constructor with brand: " + brand);
    }
 
    public static void main(String[] args) {
        Bike bike1 = new Bike();
        // Output:
        // Vehicle constructor with speed: 0
        // Vehicle constructor with speed: 50
        // Bike constructor with brand: Default Brand
        // Bike no-arg constructor called
 
        Bike bike2 = new Bike("Yamaha");
        // Output:
        // Vehicle constructor with speed: 0
        // Vehicle constructor with speed: 50
        // Bike constructor with brand: Yamaha
    }
}

6. What is the difference between the final method and abstract method?

Featurefinal Methodabstract Method
DefinitionA method that cannot be overriddenA method without implementation that must be overridden
PurposeTo restrict subclass behavior and preserve implementationTo provide a blueprint for derived classes to implement
UsageUse to prevent changes in method behaviorUse to enforce implementation in subclasses
ImplementationMust have a method bodyCannot have a method body
OverridingCannot be overriddenMust be overridden by non-abstract subclasses
Class TypeCan be in abstract or concrete classesCan only be in abstract classes
final Method:
public class Parent {
    public final void show() {
        System.out.println("This is a final method.");
    }
}
 
public class Child extends Parent {
    // Trying to override will cause a compile-time error
    // public void show() {
    //     System.out.println("Trying to override.");
    // }
}

abstract Method:

// Abstract class with an abstract method
public abstract class Animal {
    public abstract void sound();
}
 
// Concrete subclass providing implementation for the abstract method
public class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Bark");
    }
}
 
public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        dog.sound(); // Output: Bark
    }
}

7. Types of Polymorphism ?

  1. Compile Time / Static Polymorphism / Method Overloading
  2. Run Time / Dynamic Polymorphism / Method Overriding

Method Overloading: Multiple methods in the same class with the same name but different parameters. On the basis of RETURN TYPE overloading CAN’T be done.

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

Method Overriding: A method in a subclass has the same name, return type, and parameters as a method in the parent class.

public class Animal {
    void sound() {
        System.out.println("This is a generic sound.");
    }
}
 
public class Cat extends Animal {
    void sound() {
        System.out.println("The cat meows.");
    }
}
 
public class Main {
    public static void main(String[] args) {
        Animal animal = new Cat();
        animal.sound();  // Outputs: The cat meows.
    }
}

8. Difference b/w “abstraction” and “encapsulation” ? 1. Encapsulation 2. Abstraction

  • Abstraction solves the problem at design level while Encapsulation solves it implementation level.
  • In Java, Abstraction is supported using interface and abstract class while Encapsulation is supported using access modifiers e.g. public(Accessible everywhere), private(Accessible within class) and protected(Accessible in subclass and package).
  • Abstraction is about hiding unwanted details while giving out most essential details, while Encapsulation means hiding the code and data into a single unit e.g. class or method to protect inner working of an object from outside world.
AbstractionEncapsulation
Abstraction is a process of hiding the implementation details and showing only functionality to the user.Encapsulation is a process of wrapping code and data together into a single unit
Abstraction lets you focus on what the object does instead of how it does it.Encapsulation provides you the control over the data and keeping it safe from outside misuse.
Abstraction solves the problem in the Design Level.Encapsulation solves the problem in the Implementation Level.
Abstraction is implemented by using Interfaces and Abstract Classes.Encapsulation is implemented by using Access Modifiers (private, default, protected, public)
Abstraction means hiding implementation complexities by using interfaces and abstract class.Encapsulation means hiding data by using setters and getters.

9. Can there be an abstract method without an abstract class?

No, an abstract method cannot exist without an abstract class. This is because an abstract method indicates that subclasses must provide the implementation, and abstract classes are designed specifically to have such methods that act as blueprints for subclasses.

10. Can you access non static variable in static context?

No, you cannot directly access a non-static variable from a static context in Java.

  • Static context (such as static methods or static blocks) is associated with the class itself, not with any specific instance of the class.
  • Non-static variables (or instance variables) are tied to individual instances of the class.

11. Can we have multiple public classes in a java source file?

No, you cannot have multiple public classes in a single Java source file. In Java, each public class must be declared in its own file, and the name of the file must match the name of the public class. You can have multiple non-public (package-private) classes in a single Java source file. These classes will not be accessible outside their package.

12. What is the difference between abstract class and interface?

Abstract class and interface both are used to achieve abstraction where we can declare the abstract methods. Abstract class and interface both can’t be instantiated.

Abstract ClassInterface
01.Abstract class can have abstract and non-abstract methods.Interface can have only abstract methods. Since Java 8, it can have default and static methods also.
02.Abstract class doesn’t support multiple inheritance.Interface supports multiple inheritance.
03.Abstract class can have final, non-final, static and non-static variables.Interface has only static and final variables.
04.Abstract class can provide the implementation of interface.Interface can’t provide the implementation of abstract class.
05.The abstract keyword is used to declare abstract class.The interface keyword is used to declare interface.
06.An abstract class can extend another Java class and implement multiple Java interfaces.An interface can extend another Java interface only.
07.An abstract class can be extended using keyword “extends”.An interface can be implemented using keyword “implements”.
08.A Java abstract class can have class members like private, protected, etc.Members of a Java interface are public by default.

13. What are the restrictions that are applied to the Java static methods?

If a method is declared as static, it is a member of a class rather than belonging to the object of the class. It can be called without creating an object of the class. A static method also has the power to access static data members of the class.

There are a few restrictions imposed on a static method :

  • The static method cannot use non-static data member or invoke non-static method directly.
  • The this and super cannot be used in static context.
  • The static method can access only static type data (static type instance variable).
  • There is no need to create an object of the class to invoke the static method.
  • A static method cannot be overridden in a subclass

14. What is immutable object? Can you write immutable object?

Immutable objects are objects that don’t change. A Java immutable object must have all its fields be internal, private final fields. It must not implement any setters. It needs a constructor that takes a value for every single field.

Creating an Immutable Object

  • Do not add any setter method
  • Declare all fields final and private
  • If a field is a mutable object create defensive copies of it for getter methods
  • If a mutable object passed to the constructor must be assigned to a field create a defensive copy of it
  • Don’t allow subclasses to override methods.
public class DateContainer {
  private final Date date;
  public DateContainer() {
      this.date = new Date();
  }
  public Date getDate() {
    return new Date(date.getTime());
  }
}

15. The difference between Inheritance and Composition?

AspectInheritanceComposition
DefinitionA mechanism where one class (subclass) derives from another class (superclass), inheriting its attributes and behaviors.A design principle where a class is composed of one or more objects from other classes, using them as building blocks.
Relationship”Is-a” relationship. (e.g., a Dog is a Animal)“Has-a” relationship. (e.g., a Car has a Engine)
Code ReuseCode is reused by inheriting from a parent class.Code is reused by including instances of other classes.
FlexibilityLess flexible; changing the superclass affects all subclasses.More flexible; changes in component classes do not affect the container class as long as the interface remains the same.
CouplingGenerally results in tighter coupling between parent and child classes.Promotes loose coupling between classes, as they interact through interfaces or common behaviors.
OverridingAllows method overriding, enabling polymorphism.Does not support method overriding but allows delegation.
Use CasesSuitable for situations where a clear hierarchy exists.Suitable for building complex types by combining simpler components, especially when behavior can vary.
ImplementationAchieved using the extends keyword in Java.Achieved by declaring class attributes that are instances of other classes.

Example: Inheritance

class Fruit {
   //...
}
class Apple extends Fruit {
   //...
}

Example: Composition

class Fruit {
   //...
}
class Apple {
   private Fruit fruit = new Fruit();
   //...
}

16. Difference between creating String as new() and literal?

String pool : It is a pool of Strings stored in Java Heap Memory. String pool helps in saving a lot of space for Java Runtime although it takes more time to create the String.

AspectUsing new KeywordUsing String Literals
SyntaxString str = new String("Hello");String str = "Hello";
Memory AllocationCreates a new String object in the heap memory every time.Reuses existing String objects from the String pool if the same literal already exists
String PoolDoes not use the String pool; each new creates a distinct objectUses the String pool, optimizing memory usage by sharing instances
Equality Checknew String("Hello") == new String("Hello") returns false (different references)"Hello" == "Hello" returns true (same reference if in pool)
PerformanceGenerally slower due to the creation of a new object each timeMore efficient as it reuses existing objects from the String pool
Use CaseUsed when you explicitly want a new instance of a String, not shared with othersRecommended for normal string usage to leverage memory efficiency

17. How can we create an immutable class in Java?

Immutable class means that once an object is created, we cannot change its content. In Java, all the wrapper classes (like Integer, Boolean, Byte, Short) and String class is immutable.

Rules to create immutable classes

  • The class must be declared as final (So that child classes can’t be created)
  • Data members in the class must be declared as final (So that we can’t change the value of it after object creation)
  • A parameterized constructor
  • Getter method for all the variables in it
  • No setters(To not have the option to change the value of the instance variable)
public final class Employee {  
 
   final String pancardNumber;  
   
   public Employee(String pancardNumber) {  
      this.pancardNumber = pancardNumber;  
   }  
   public String getPancardNumber() {  
      return pancardNumber;  
   }
}  

18. What is difference between String, StringBuffer and StringBuilder?

Mutability Difference:  String is immutable, if you try to alter their values, another object gets created, whereas StringBufferand StringBuilder are mutable so they can change their values.

Thread-Safety Difference: The difference between StringBuffer and StringBuilder is that StringBuffer is thread-safe. So when the application needs to be run only in a single thread then it is better to use StringBuilder. StringBuilder is more efficient than StringBuffer.

19. What are the differences between throw and throws?

Throw keyword is used in the method body to throw an exception, while throws is used in method signature to declare the exceptions that can occur in the statements present in the method.

20. Why string is immutable in java?

  • The string is Immutable in Java because String objects are cached in String pool. Since cached String literals are shared between multiple clients there is always a risk, where one client’s action would affect all another client.
  • Since string is immutable it can safely share between many threads and avoid any synchronization issues in java.

21. How Garbage collector algorithm works?

Garbage collection works on Mark and Sweep algorithm. In Mark phase it detects all the unreachable objects and Sweep phase it reclaim the heap space used by the garbage objects and make the space available again to the program.

22. What will be the problem if you do not override hashcode() method?

If you do not override the hashCode() method when you override the equals() method in a class, you may run into issues with data structures that use hashing, such as HashSet, HashMap, and Hashtable. These collections rely on hashCode() to efficiently locate and group objects.

Key Problems:

  1. Inconsistent Behavior: If two objects are considered equal according to the equals() method, but their hashCode() methods return different values, the collections will treat them as different entries. This violates the general contract of hashCode(), which states that if two objects are equal according to the equals(Object) method, then calling the hashCode() method on each of the two objects must produce the same integer result.
  2. Data Integrity Issues: If the hashCode() is not consistent with equals(), it can lead to data integrity issues where duplicate entries might be allowed in sets, or incorrect entries might exist in maps, leading to unexpected behavior and bugs in your program.
Example Issue 👇🏼
public class Person {
    private String name;
    private int age;
 
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
 
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return age == person.age && Objects.equals(name, person.name);
    }
 
    // No hashCode() override here.
}
 
// Using HashSet
HashSet<Person> set = new HashSet<>();
set.add(new Person("John", 30));
set.add(new Person("John", 30));
 
System.out.println(set.size()); // Output might unexpectedly be 2 instead of 1

Java Collections

23. What is difference between ArrayList and LinkedList?

ArrayList and LinkedList both implements List interface and maintains insertion order. Both are non synchronized classes.

Sl.NoArrayListLinkedList
01.ArrayList internally uses a dynamic array to store the elements.LinkedList internally uses a doubly linked list to store the elements.
02.Manipulation with ArrayList is slow because it internally uses an array. If any element is removed from the array, all the bits are shifted in memory.Manipulation with LinkedList is faster than ArrayList because it uses a doubly linked list, so no bit shifting is required in memory.
03.An ArrayList class can act as a list only because it implements List only.LinkedList class can act as a list and queue both because it implements List and Deque interfaces.
04.ArrayList is better for storing and accessing data.LinkedList is better for manipulating data.

24. What is the difference between HashMap and ConcurrentHashMap?

HashMapConcurrentHashMap
HashMap is not synchronized.ConcurrentHashMap is synchronized.
HashMap is not thread safe.ConcurrentHashMap is thread safe.
HashMap iterator is fail-fast and ArrayList throws ConcurrentModificationException if concurrent modification happens during iteration.ConcurrentHashMap is fail-safe and it will never throw ConcurrentModificationException during iteration.
HashMap allows key and value to be null.ConcurrentHashMap does not allow null key/value. It will throw NullPointerException.
HashMap is faster.ConcurrentHashMap is slower than HashMap.

25. What is the difference ConcurrentHashMap and Hashtable?

AspectHashtableConcurrentHashMap
Locking MechanismSingle lock for the entire table, blocking all accessFine-grained locking (segments), allowing concurrent access
Read OperationsSynchronized reads, blocking access for all other threadsNon-blocking reads, allowing multiple threads to read simultaneously
Write OperationsLocks the entire table for writes, causing contentionLocks only the affected segment, allowing other segments to be accessed
Concurrency LevelNot configurable; all threads share the same lockConfigurable concurrency level for optimal performance
ScalabilityScalability is limited under heavy multi-threaded accessScales better with increasing threads, minimizing contention
PerformanceSlower due to global locking and contention issuesGenerally faster due to reduced locking overhead

26. How HashMap works in Java? (!MPORTANT !)

  1. Hashing : When you add an element using the put(key, value) method, Java calls the hashCode() method on the key to calculate its hash value. This hash value is then used to determine the index of the bucket where the key-value pair will be stored.

  2. Index Calculation: The hash code is further processed (usually using bitwise operations) to find the specific index in an internal array called the bucket array. This calculation is done to evenly distribute entries across the buckets and avoid clustering.

  3. Storing Entries: Each bucket can contain multiple entries. If the bucket is empty, the new key-value pair is simply added. If the bucket already contains entries, HashMap checks if there’s a key collision.

  4. Handling Collisions:  If two keys hash to the same index (a collision), HashMap resolves this by using chaining, where multiple entries can exist in a single bucket. Each bucket typically holds a linked list or a tree structure (since Java 8) to handle collisions more efficiently.

  5. Retrieving Values: When you call the get(key) method, HashMap again calculates the hash code of the key and finds the bucket index. It then searches the bucket (linked list or tree) for the key using the equals() method to find the corresponding value.

  6. Performance: In the worst case this degrades the performance of the get() method of HashMap to O(n) from O(1). In order to address this issue in the case of frequent HashMap collisions, Java 8 has started using a balanced tree instead of linked list for storing collided entries. This also means that in the worst case you will get a performance boost from O(n) to O(log n).

			     +-----------------------------+
			     |         HashMap             |
			     +-----------------------------+
	                          |
	                          v
              +---------------------------------+
              |   Internal Array (Buckets)      |
              |---------------------------------|
   Index 0 -> | [ ] -> [Key1, Value1]           |
              |---------------------------------|
   Index 1 -> | [ ]                             |
              |---------------------------------|
   Index 2 -> | [ ] -> [Key2, Value2] -> [Key3, Value3] (Collision) 
              |---------------------------------|
   Index 3 -> | [ ]                             |
              |---------------------------------|
   Index 4 -> | [ ] -> [Key4, Value4]           |
              |---------------------------------|
   Index 5 -> | [ ]                             |
              |---------------------------------|
   Index 6 -> | [ ] -> [Key5, Value5]           |
              |---------------------------------|
   Index 7 -> | [ ]                             |
              +---------------------------------+

Summary of Key Steps:

  • Compute hash code using hashCode() and determine bucket index.
  • Store entry in the corresponding bucket.
  • Handle collisions using linked lists or trees within buckets.
  • Retrieve values by locating the bucket and searching within it.

26. What happens when a duplicate key is put into a HashMap?

  1. Value Replacement: The new value replaces the existing value associated with that key. This means that the previous value is dropped from the HashMap.
  2. Garbage Collection: If no other references to the previous value exist outside the HashMap, that value becomes eligible for garbage collection, meaning it can be reclaimed by the Java Virtual Machine (JVM) to free up memory.
  3. Return Value: The put() method returns the old value that was associated with the key. If the key was not previously present in the map, it returns null. This allows you to check what the previous value was before the update.

Design Patterns in JAVA

27. Explain Singleton Design Pattern in Java?

1. Eager initialization:
In eager initialization, the instance of Singleton Class is created at the time of class loading.

Example:

public class EagerInitializedSingleton {
    
    private static final EagerInitializedSingleton instance = new EagerInitializedSingleton();
    
    // private constructor to avoid client applications to use constructor
    private EagerInitializedSingleton(){}
 
    public static EagerInitializedSingleton getInstance(){
        return instance;
    }
}

2. Static block initialization
Static block initialization implementation is similar to eager initialization, except that instance of class is created in the static block that provides option for exception handling.

Example:

public class StaticBlockSingleton  {
 
    private static StaticBlockSingleton  instance;
    
    private StaticBlockSingleton (){}
    
    // static block initialization for exception handling
    static{
        try{
            instance = new StaticBlockSingleton ();
        }catch(Exception e){
            throw new RuntimeException("Exception occured in creating Singleton instance");
        }
    }
    
    public static StaticBlockSingleton getInstance(){
        return instance;
    }
}

3. Lazy Initialization
Lazy initialization method to implement Singleton pattern creates the instance in the global access method.

Example:

public class LazyInitializedSingleton  {
 
    private static LazyInitializedSingleton  instance;
    
    private LazyInitializedSingleton(){}
    
    public static LazyInitializedSingleton getInstance(){
        if(instance == null){
            instance = new LazyInitializedSingleton ();
        }
        return instance;
    }
}

4. Thread Safe Singleton
The easier way to create a thread-safe singleton class is to make the global access method synchronized, so that only one thread can execute this method at a time.

Example:

public class ThreadSafeSingleton {
 
    private static ThreadSafeSingleton instance;
    
    private ThreadSafeSingleton(){}
    
    public static synchronized ThreadSafeSingleton getInstance(){
        if(instance == null){
            instance = new ThreadSafeSingleton();
        }
        return instance;
    }
}