1. Can we create an object using an anonymous class?
No, we cannot create an object of an abstract class because it may
contain abstract methods with no implementation. However, we can
create a reference of the abstract class and assign it to an object of its
concrete subclass, which is a common way to achieve runtime
polymorphism. We can also instantiate an anonymous subclass of the
abstract class.
2. Why do abstract classes have constructors?
An abstract class cannot be instantiated, but its constructor is
executed when a subclass object is created. It is mainly used to
initialize common fields and perform shared setup.
3. Abstract Class vs Interface
Abstract Class Interface
Can have abstract Traditionally abstract methods only; since
and concrete Java 8, can also have default and static
methods methods; Java 9 added private methods
Supports
No constructors
constructors
Can have instance
Can have only public static final constants
variables
Uses extends Uses implements
Single inheritance Multiple interfaces can be implemented
Can have any Interface methods are public by default
access modifiers (unless private helper methods)
Used for closely
Used to define a common capability/contract
related classes
4. When to use an Abstract Class?
Classes share code and state.
You want common fields and implementations.
Example:
5. When to use an Interface?
Unrelated classes share a capability.
You need multiple inheritance of behavior.
Example:
"Use an abstract class when related classes need shared state and behavior.
Use an interface when different classes need to follow the same contract and
you want the flexibility of multiple inheritance."
6. Normal Interface
Contains two or more abstract methods (though from Java 8 onward, it
may also contain default and static methods).
Example:
7. Functional Interface (Java 8)
A functional interface has exactly one abstract method.
It can also have multiple default and static methods.
Annotated with @FunctionalInterface (optional but recommended).
Example
8. Arraylist internal Implementation
When an element is removed from an ArrayList, Java shifts all subsequent
elements one position to the left using [Link](). The last occupied
slot is set to null to avoid memory leaks, the size is decremented, and the
capacity remains unchanged. Since shifting may involve many elements,
removing from the middle of an ArrayList has a time complexity of O(n)
9. Linked list implementation
LinkedList in Java is implemented as a doubly linked list. Each node stores
the element along with references to the previous and next nodes. The
LinkedList class maintains pointers to the first and last nodes, making
insertion and deletion at either end O(1). Random access is slower because it
must traverse the list from either the beginning or the end depending on the
index, making get(index) O(n). Unlike ArrayList, LinkedList does not shift
elements during insertion or deletion; it only updates node references
10. HashMap implementation
HashMap is implemented using an array of buckets. Each bucket stores
nodes containing the key, value, hash, and a reference to the next node.
During put (), Java computes the key's hash Code (), determines the bucket
index using (n - 1) & hash, and inserts the entry into that bucket. If multiple
keys map to the same bucket, a collision occurs. Collisions are handled using
a linked list, and in Java 8+, if a bucket contains 8 or more nodes and the
table size is at least 64, it is converted into a Red-Black Tree for faster
lookups. The default capacity is 16 with a load factor of 0.75, so the map
resizes when it exceeds 12 entries. Average time complexity for put() and
get() is O(1).
If we insert the same key with a different value into a HashMap, the existing
value is replaced. HashMap identifies the existing entry using the key's
hashCode() and equals() method. It updates the value in the existing node
instead of creating a new entry. Therefore, duplicate keys are not allowed,
but duplicate values are allowed.
11. ConcurrentHashMap implementation
ConcurrentHashMap is a thread-safe implementation of the Map interface
optimized for concurrent access. Unlike Hashtable, which synchronizes every
method and locks the entire map, ConcurrentHashMap uses fine-grained
synchronization. In Java 8+, it uses CAS for inserting into empty buckets and
locks only the specific bucket during updates. Read operations are generally
lock-free, making them very fast. Like HashMap, it handles collisions using
linked lists and converts heavily populated buckets into Red-Black Trees
when appropriate. It does not allow null keys or values to avoid ambiguity
during concurrent reads.
12. HashSet Implementation
HashSet is internally implemented using a HashMap. Every element added to
the HashSet is stored as a key in the underlying HashMap, while all values
are the same dummy object called PRESENT. When add() is called, HashSet
internally executes [Link](element, PRESENT). Since HashMap does not
allow duplicate keys, duplicate elements are automatically ignored. HashSet
uses hashCode() to locate the bucket and equals() to detect duplicates. The
average time complexity for add(), remove(), and contains() is O(1)
13. TreeMap Implementation
TreeMap is implemented using a Red-Black Tree, which is a self-balancing
Binary Search Tree. Each node stores the key, value, parent, left child, right
child, and a color (red or black). When a key is inserted, TreeMap places it
according to BST rules and then performs rotations and recoloring if needed
to maintain balance. This guarantees that put(), get(), and remove() all run in
O(log n) time. Unlike HashMap, TreeMap stores keys in sorted order and
does not allow null keys because key comparison is required to maintain the
tree structure.
14. JVM Architecture
The JVM executes Java bytecode. It first loads classes using the Class Loader,
stores class metadata in the Method Area and objects in the Heap, while
each thread has its own Stack, PC Register, and Native Method Stack. The
Execution Engine runs the bytecode using the Interpreter and optimizes
frequently executed code with the JIT Compiler. The Garbage Collector
automatically reclaims unused heap memory, and the JNI allows Java to
interact with native C/C++ libraries. This architecture is what makes Java
platform-independent and efficient.