Programming & OOP Interview Questions
Programming concepts, OOP principles, and language-specific features for Java, Python, C++, and JavaScript
1 What are the four pillars of Object-Oriented Programming?
Easy
What are the four pillars of Object-Oriented Programming?
The four pillars are: 1) Encapsulation - bundling data and methods, hiding internal state; 2) Abstraction - hiding complexity, exposing only essential features; 3) Inheritance - creating new classes from existing ones, promoting code reuse; 4) Polymorphism - objects of different classes responding to same method differently. These principles help create modular, reusable, and maintainable code. Encapsulation protects data, abstraction simplifies interfaces, inheritance enables hierarchies, and polymorphism allows flexible code.
2 What is the difference between a class and an object?
Easy
What is the difference between a class and an object?
A class is a blueprint or template that defines properties (attributes) and behaviors (methods) that objects of that type will have. An object is an instance of a class - a concrete entity created from the class blueprint with actual values. For example, 'Car' is a class defining attributes like color and speed, while 'myCar' is an object with color='red' and speed=100. Classes define the structure; objects are the actual entities in memory.
3 What is the difference between method overloading and method overriding?
Easy
What is the difference between method overloading and method overriding?
Method overloading (compile-time polymorphism) has multiple methods with the same name but different parameters in the same class. The compiler determines which method to call based on arguments. Method overriding (runtime polymorphism) has a subclass providing a specific implementation of a method already defined in its parent class. The JVM determines which method to call based on the actual object type at runtime. Overloading is about different signatures; overriding is about different implementations.
4 What is the difference between an abstract class and an interface?
Easy
What is the difference between an abstract class and an interface?
Abstract class can have both abstract and concrete methods, instance variables, constructors, and supports single inheritance. Interface (traditionally) only has abstract methods and constants, supports multiple inheritance. Use abstract class for 'is-a' relationship with shared implementation; use interface for 'can-do' capabilities. In Java 8+, interfaces can have default methods. Abstract classes are partially implemented templates; interfaces define contracts. Choose based on whether you need shared state/implementation (abstract class) or pure contracts (interface).
5 What is the difference between a list and a tuple in Python?
Easy
What is the difference between a list and a tuple in Python?
Lists are mutable (can be modified after creation), use square brackets [], and are used for collections that may change. Tuples are immutable (cannot be modified), use parentheses (), and are used for fixed collections. Tuples are faster than lists due to immutability and can be used as dictionary keys. Lists have methods like append() and remove(); tuples don't. Use tuples for coordinates, database records, or when you want to ensure data integrity. Use lists when you need to modify the collection.
Get IIT Jammu PG Certification
Master these concepts with 175+ hours of industry projects and hands-on training.
6 What does the static keyword mean in Java?
Easy
What does the static keyword mean in Java?
Static members belong to the class rather than instances. Static variables are shared across all instances (class-level storage). Static methods can be called without creating an object and cannot access non-static members. Static blocks execute once when class is loaded for initialization. Common uses: utility methods (Math.sqrt()), constants (static final), factory methods, counters shared across instances. Static members are stored in method area, not heap. Access via ClassName.member, not instance reference.
7 What is a constructor and what is its purpose?
Easy
What is a constructor and what is its purpose?
A constructor is a special method called when an object is created, used to initialize the object's state. It has the same name as the class and no return type. Default constructor (no arguments) is provided by compiler if none defined. Parameterized constructors accept arguments for initialization. Constructor overloading allows multiple constructors with different parameters. In Java, 'this()' calls another constructor; 'super()' calls parent constructor. Constructors ensure objects are in valid state from creation.
8 What are decorators in Python?
Easy
What are decorators in Python?
Decorators are functions that modify the behavior of other functions without changing their code. They use @decorator_name syntax above function definitions. Decorators take a function as input, add functionality, and return a modified function. Common uses: logging, timing, authentication, caching (@lru_cache). Example: @property converts method to attribute access. Decorators enable aspect-oriented programming. Multiple decorators can be stacked. They leverage Python's first-class functions (functions as objects). Built-in decorators include @staticmethod, @classmethod, @property.
9 What is the difference between pass by value and pass by reference?
Easy
What is the difference between pass by value and pass by reference?
Pass by value creates a copy of the argument; changes inside the function don't affect the original. Pass by reference passes the memory address; changes inside the function modify the original. Java is always pass by value, but for objects, the reference is passed by value (can modify object's state but not reassign reference). C++ supports both explicitly with & for reference. Python passes object references by value (mutable objects can be modified, immutable cannot). Understanding this prevents bugs with unintended modifications.
10 What does the final keyword do in Java?
Easy
What does the final keyword do in Java?
Final has three uses: 1) Final variable cannot be reassigned after initialization (constant). For objects, the reference is final but object state can change. 2) Final method cannot be overridden by subclasses, ensuring consistent behavior. 3) Final class cannot be extended (e.g., String, Integer). Benefits: thread safety (immutable variables), security (prevent overriding), optimization (JVM can inline final methods). Use for constants (static final), preventing inheritance, and ensuring method behavior.
11 What is the difference between var, let, and const in JavaScript?
Easy
What is the difference between var, let, and const in JavaScript?
var is function-scoped, hoisted with undefined initialization, can be redeclared and reassigned. let is block-scoped, hoisted but not initialized (temporal dead zone), cannot be redeclared, can be reassigned. const is block-scoped, must be initialized at declaration, cannot be reassigned (but object properties can change). Best practices: use const by default, let when reassignment needed, avoid var. let and const were introduced in ES6 to fix var's scoping issues and provide clearer intent.
12 What is encapsulation and why is it important?
Easy
What is encapsulation and why is it important?
Encapsulation bundles data (attributes) and methods that operate on that data within a single unit (class), restricting direct access to internal state. Implementation: private fields with public getter/setter methods. Benefits: data hiding (implementation can change without affecting users), validation (setters can validate input), controlled access, reduced coupling. Example: BankAccount with private balance, public deposit() and withdraw() methods that validate amounts. Encapsulation is foundation for maintaining invariants and building robust systems.
13 What is the purpose of 'self' in Python?
Easy
What is the purpose of 'self' in Python?
self is a reference to the current instance of the class, used to access instance attributes and methods. It must be the first parameter of instance methods (though not passed when calling). self.attribute creates/accesses instance variables; without self, it's a local variable. Unlike Java/C++ where 'this' is implicit, Python requires explicit self. Convention is to use 'self' though any name works. Class methods use 'cls' instead of 'self'. self enables each object to maintain its own state.
14 What is the difference between pointers and references in C++?
Easy
What is the difference between pointers and references in C++?
Pointers store memory addresses, can be null, can be reassigned, require dereferencing (*) to access value, use -> for member access. References are aliases to existing variables, cannot be null, must be initialized, cannot be reassigned, access value directly. Pointers allow arithmetic and dynamic memory; references are safer and cleaner. Use references for function parameters (avoid copying, allow modification). Use pointers when null is valid, reassignment needed, or for dynamic allocation. References are preferred when possible for safety.
15 What are the different types of inheritance?
Easy
What are the different types of inheritance?
Single inheritance: one class inherits from one parent. Multi-level inheritance: chain of inheritance (A -> B -> C). Hierarchical inheritance: multiple classes inherit from one parent. Multiple inheritance: one class inherits from multiple parents (C++, Python support; Java uses interfaces). Hybrid inheritance: combination of types. Issues: Diamond problem in multiple inheritance (ambiguity when same member inherited via different paths). Solutions: virtual inheritance (C++), method resolution order MRO (Python), interfaces (Java). Choose inheritance type based on relationship modeling needs.
3,000+ Engineers Placed at Top Companies
Join Bosch, Tata Motors, L&T, Mahindra and 500+ hiring partners.
16 Explain the SOLID principles of object-oriented design.
Medium
Explain the SOLID principles of object-oriented design.
SOLID: S - Single Responsibility: class should have one reason to change. O - Open/Closed: open for extension, closed for modification. L - Liskov Substitution: subtypes must be substitutable for base types without breaking behavior. I - Interface Segregation: many specific interfaces better than one general interface. D - Dependency Inversion: depend on abstractions, not concretions. Following SOLID leads to maintainable, flexible, testable code. Example violations: God classes (SRP), switch statements on types (OCP), square inheriting rectangle (LSP).
17 How does garbage collection work in Java?
Medium
How does garbage collection work in Java?
Java GC automatically reclaims memory from unreachable objects. Heap divided into generations: Young (Eden + Survivor spaces) for new objects, Old/Tenured for long-lived objects. Minor GC cleans Young generation frequently; Major GC cleans Old generation (slower). Algorithms: Serial, Parallel, CMS (deprecated), G1 (default in Java 9+), ZGC/Shenandoah (low-latency). G1 divides heap into regions, collects regions with most garbage first. GC roots: stack references, static fields, JNI references. Tuning: heap size, generation ratios, GC algorithm selection.
18 What are generators in Python and when should you use them?
Medium
What are generators in Python and when should you use them?
Generators are functions that yield values one at a time, maintaining state between calls, using lazy evaluation. Created with 'yield' keyword or generator expressions (x for x in range(n)). Benefits: memory efficient (values generated on demand, not stored), infinite sequences possible, pipeline composition. Use when: processing large files line by line, streaming data, when you don't need all values at once. Methods: __next__(), send(), throw(), close(). Example: reading million-line file without loading entire file. Generators are iterators with simpler syntax.
19 How does synchronization work in Java?
Medium
How does synchronization work in Java?
synchronized ensures only one thread executes critical section at a time. Synchronized methods lock on 'this' (instance) or class object (static). Synchronized blocks lock on specified object, offering finer control. Each object has intrinsic lock (monitor). Thread acquires lock on entry, releases on exit. wait() releases lock and waits for notify(); notify()/notifyAll() wake waiting threads. Alternatives: ReentrantLock (explicit lock/unlock, tryLock, fairness), ReadWriteLock (multiple readers OR single writer). Synchronization prevents race conditions but can cause deadlocks.
20 What are smart pointers in C++ and when should you use each type?
Medium
What are smart pointers in C++ and when should you use each type?
Smart pointers automate memory management using RAII. unique_ptr: exclusive ownership, non-copyable, movable. Use for single owner resources. shared_ptr: shared ownership via reference counting, copied increments count, deletion when count reaches zero. Use when multiple owners needed. weak_ptr: non-owning reference to shared_ptr, doesn't affect count, check validity with lock(). Use to break circular references. make_unique and make_shared preferred for creation. Smart pointers prevent memory leaks and dangling pointers. Avoid raw pointers for ownership; use for non-owning references.
21 What are closures in JavaScript and how are they used?
Medium
What are closures in JavaScript and how are they used?
A closure is a function that remembers variables from its outer (enclosing) scope even after the outer function has returned. The inner function maintains a reference to the outer scope's variables. Uses: data privacy (module pattern), function factories, callbacks with state, memoization, partial application/currying. Example: counter factory where inner function accesses and modifies outer variable. Closures enable functional programming patterns. Caution: closures in loops can cause issues (use let or IIFE). Understanding closures is essential for advanced JavaScript patterns.
22 Implement and explain the Singleton design pattern.
Medium
Implement and explain the Singleton design pattern.
Singleton ensures a class has only one instance with global access. Implementation: private constructor, private static instance, public static getInstance() method. Thread-safe options: synchronized getInstance (slow), eager initialization (simple), double-checked locking (volatile + sync), enum singleton (Java, best practice), static holder class (lazy, thread-safe). Use cases: logging, configuration, connection pools. Criticisms: global state, testing difficulty, hidden dependencies. Consider dependency injection as alternative. Ensure: private constructor, static instance, controlled access.
23 What is the Global Interpreter Lock (GIL) in Python?
Medium
What is the Global Interpreter Lock (GIL) in Python?
GIL is a mutex in CPython that allows only one thread to execute Python bytecode at a time, even on multi-core systems. Purpose: simplifies memory management, makes C extensions easier. Impact: CPU-bound tasks don't benefit from multi-threading. Solutions: multiprocessing (separate processes, no GIL), use C extensions that release GIL, asyncio for I/O-bound tasks, alternative implementations (Jython, PyPy). I/O-bound code releases GIL during I/O operations, so threading works well. For CPU-bound parallelism, use multiprocessing or ProcessPoolExecutor.
24 Explain Java Streams API and its key operations.
Medium
Explain Java Streams API and its key operations.
Streams API (Java 8+) enables functional-style operations on collections. Pipeline: source -> intermediate operations -> terminal operation. Intermediate (lazy): filter, map, flatMap, sorted, distinct, limit, skip. Terminal (eager): forEach, collect, reduce, count, findFirst, anyMatch. Parallel streams: .parallelStream() for concurrent processing. Collectors: toList, toSet, groupingBy, joining. Benefits: declarative code, parallelization, lazy evaluation. Example: list.stream().filter(x -> x > 0).map(x -> x * 2).collect(toList()). Streams are single-use; create new stream for reprocessing.
25 What is dependency injection and what are its benefits?
Medium
What is dependency injection and what are its benefits?
Dependency Injection (DI) provides dependencies to objects rather than objects creating them. Types: constructor injection (preferred, immutable), setter injection (optional dependencies), interface injection (rarely used). Benefits: loose coupling (depend on abstractions), testability (inject mocks), flexibility (swap implementations), adherence to SOLID. Frameworks: Spring (Java), Dagger (Java/Android), Angular (TypeScript). Example: PaymentService receives PaymentGateway via constructor instead of creating it. DI container manages object creation and lifecycle. Follows Dependency Inversion Principle.
Harshal
Fiat Chrysler
Abhishek
TATA ELXSI
Srinithin
Xitadel
Ranjith
Core Automotive
Gaurav
Automotive Company
Bino
Design Firm
Aseem
EV Company
Puneet
Automotive Company
Vishal
EV Startup
More Success Stories
26 Explain async/await in Python and when to use it.
Medium
Explain async/await in Python and when to use it.
asyncio enables concurrent I/O-bound operations in single thread. async def defines coroutine; await pauses execution until awaitable completes. Event loop manages coroutine scheduling. Use for: network requests, file I/O, database queries, web scraping. asyncio.gather() runs coroutines concurrently. aiohttp, asyncpg for async libraries. Benefits: efficient I/O (no thread overhead), simpler than callbacks. NOT for CPU-bound tasks (GIL still applies). Example: fetching multiple URLs concurrently. Pattern: async with, async for for async context managers and iterators.
27 What is RAII in C++ and why is it important?
Medium
What is RAII in C++ and why is it important?
RAII (Resource Acquisition Is Initialization) ties resource lifecycle to object lifetime. Acquire resources in constructor, release in destructor. When object goes out of scope, destructor automatically releases resources. Examples: smart pointers for memory, file handles, mutex locks (std::lock_guard), database connections. Benefits: exception safety (destructor called during stack unwinding), no resource leaks, deterministic cleanup, cleaner code (no explicit cleanup). RAII is fundamental C++ idiom. Standard library extensively uses RAII: fstream, unique_lock, shared_ptr.
28 Explain Promises and async/await in JavaScript.
Medium
Explain Promises and async/await in JavaScript.
Promises represent eventual completion (or failure) of async operation. States: pending, fulfilled, rejected. then() for success, catch() for errors, finally() always runs. Promise.all() waits for all, Promise.race() for first. async/await (ES2017) is syntactic sugar: async function returns Promise, await pauses until Promise resolves. Error handling: try/catch with await vs .catch(). async/await makes async code look synchronous. Combine: await Promise.all([...]) for concurrent operations. Never use await in loops for parallel operations; use Promise.all instead.
29 Explain exception handling in Java and best practices.
Medium
Explain exception handling in Java and best practices.
Exceptions represent runtime errors. Hierarchy: Throwable -> Error (unrecoverable), Exception -> RuntimeException (unchecked), other checked exceptions. Try-catch-finally: catch handles exception, finally always executes (cleanup). Multi-catch: catch (IOException | SQLException e). Try-with-resources: automatically closes AutoCloseable resources. Best practices: catch specific exceptions, don't catch Throwable/Error, don't swallow exceptions silently, throw early catch late, use custom exceptions for domain errors. Checked vs unchecked: checked for recoverable conditions, unchecked for programming errors.
30 When should you prefer composition over inheritance?
Medium
When should you prefer composition over inheritance?
Composition (has-a) includes objects as fields; inheritance (is-a) extends classes. Prefer composition when: relationship isn't truly is-a, you need flexibility to change behavior, avoiding deep hierarchies, reusing across unrelated classes. Inheritance problems: tight coupling, fragile base class, hierarchy explosion. Composition benefits: loose coupling, runtime flexibility, easier testing. Example: instead of Stack extending ArrayList, Stack contains ArrayList. Strategy pattern uses composition for interchangeable algorithms. 'Favor composition over inheritance' - Gang of Four.
31 What are metaclasses in Python?
Medium
What are metaclasses in Python?
Metaclasses are 'classes of classes' - they define how classes behave. Class is instance of metaclass (usually 'type'). Use: class MyClass(metaclass=MyMeta). Metaclass __new__ creates class, __init__ initializes it. Use cases: registering classes automatically, enforcing API contracts, adding methods/attributes, ORMs (Django models), abstract base classes. Example: auto-register all subclasses of a base class. Most Python code doesn't need metaclasses - use decorators, class decorators, or __init_subclass__ when possible. 'Metaclasses are deeper magic than 99% of users need.'
32 What are the key concepts of functional programming?
Medium
What are the key concepts of functional programming?
Core concepts: 1) Pure functions - same input always gives same output, no side effects. 2) Immutability - data never changes, create new values. 3) First-class functions - functions as values, passed and returned. 4) Higher-order functions - take or return functions (map, filter, reduce). 5) Referential transparency - expression replaceable by its value. 6) Recursion instead of loops. Benefits: predictable, testable, parallelizable. Languages: Haskell, Clojure, Scala, F#. FP features in mainstream: lambdas, streams (Java), comprehensions (Python), array methods (JavaScript).
33 Explain the Java Memory Model and volatile keyword.
Medium
Explain the Java Memory Model and volatile keyword.
JMM defines how threads interact through memory. Each thread may have local cache; without synchronization, threads may see stale values. volatile guarantees: visibility (writes immediately visible to all threads), prevents reordering around volatile access. Not atomic for compound operations (i++). Happens-before: establishes ordering (unlock before lock, volatile write before read, thread start/join). Use volatile for: flags, status variables, simple communication. Use synchronized/locks for: compound operations, multiple related variables. volatile + CAS enables lock-free algorithms.
34 What are generics in TypeScript and how are they used?
Medium
What are generics in TypeScript and how are they used?
Generics enable type-safe reusable components that work with different types. Syntax: function identity<T>(arg: T): T { return arg; }. Type parameter <T> is placeholder for actual type. Use cases: type-safe containers/collections, utility types, factory functions. Constraints: <T extends SomeType> limits acceptable types. Multiple parameters: <K, V>. Default types: <T = string>. Generic classes, interfaces supported. Built-in: Array<T>, Promise<T>, Map<K,V>. Benefits: type safety without sacrificing flexibility, better IDE support, catch errors at compile time.
35 Explain move semantics in C++11 and when to use them.
Medium
Explain move semantics in C++11 and when to use them.
Move semantics transfer resources from temporary objects instead of copying. Rvalue references (T&&) bind to temporaries/movable values. std::move casts to rvalue reference, enabling move. Move constructor/assignment: steal resources from source, leave source in valid but unspecified state. Benefits: avoid expensive copies of containers, strings; enable unique_ptr. Rule of Five: if you define destructor/copy, define move too. Use: returning local objects (guaranteed move), moving into containers, std::swap. Move is usually O(1) vs copy O(n). Perfect forwarding: std::forward preserves value category.
36 Explain the JVM architecture and class loading mechanism.
Hard
Explain the JVM architecture and class loading mechanism.
JVM components: Class Loader Subsystem (loads .class files), Runtime Data Areas (method area, heap, stack, PC registers, native method stack), Execution Engine (interpreter, JIT compiler, GC). Class loading: Bootstrap (core Java classes), Extension, Application loaders. Loading phases: load (read bytecode), link (verify, prepare, resolve), initialize (static blocks). Class loaders follow delegation model - child delegates to parent first. Custom class loaders enable: hot deployment, isolation, dynamic loading. JIT compiles hot code to native. Metaspace (Java 8+) replaces PermGen for class metadata.
37 How does Python manage memory and garbage collection?
Hard
How does Python manage memory and garbage collection?
Python uses private heap for objects, memory manager handles allocation. Reference counting: each object tracks references, deallocated when count reaches 0. Limitation: can't handle circular references. Generational GC: objects in 3 generations (0, 1, 2), younger collected more often. Cyclic garbage collector detects reference cycles using container traversal. Memory pools: small objects from pools (pymalloc), large from OS. Interning: small integers (-5 to 256) and short strings cached. Memory profiling: tracemalloc, memory_profiler. Avoid: circular references, large lists (use generators), holding references unnecessarily.
38 Explain common concurrency patterns and their implementations.
Hard
Explain common concurrency patterns and their implementations.
Producer-Consumer: producers add to queue, consumers process. Use blocking queue (Java BlockingQueue, Python queue.Queue). Thread Pool: reuse threads for tasks, avoid creation overhead (ExecutorService, ThreadPoolExecutor). Future/Promise: represent async result, chain with then/map. Actor Model: isolated actors communicate via messages (Akka, Erlang). Read-Write Lock: multiple readers OR single writer. Semaphore: limit concurrent access to resource. Barrier: synchronization point for multiple threads. Fork-Join: divide work, process in parallel, combine results. Choose based on: task nature, coordination needs, performance requirements.
39 What is template metaprogramming in C++ and what are its applications?
Hard
What is template metaprogramming in C++ and what are its applications?
Template metaprogramming (TMP) performs computation at compile time using templates. Templates are Turing-complete - can compute anything. Techniques: recursive template instantiation, template specialization, SFINAE (substitution failure is not an error), constexpr (C++11+), if constexpr (C++17). Applications: type traits (std::is_integral), compile-time assertions, loop unrolling, expression templates (Eigen), policy-based design. Benefits: zero runtime overhead, type-safe. Drawbacks: complex syntax, long compile times, cryptic errors. Modern C++ (concepts, constexpr) simplifies many TMP use cases.
40 How would you tune JVM performance for a high-throughput application?
Hard
How would you tune JVM performance for a high-throughput application?
Heap sizing: -Xms/-Xmx (start/max heap), typically same to avoid resizing. GC selection: G1 for balanced, ZGC/Shenandoah for low latency, Parallel for throughput. Young gen ratio: -XX:NewRatio or NewSize. G1 tuning: MaxGCPauseMillis, InitiatingHeapOccupancyPercent. Monitoring: GC logs (-Xlog:gc*), jstat, jconsole, VisualVM. Metaspace: -XX:MaxMetaspaceSize. Code cache: -XX:ReservedCodeCacheSize. Analysis: heap dumps for memory leaks, thread dumps for contention. String deduplication: -XX:+UseStringDeduplication. Profile first (JMH, async-profiler), then tune. Avoid premature optimization.
41 Explain Python's descriptor protocol and its applications.
Hard
Explain Python's descriptor protocol and its applications.
Descriptors are objects with __get__, __set__, and/or __delete__ methods, controlling attribute access. Data descriptors: define __set__ or __delete__. Non-data descriptors: only __get__. Lookup order: data descriptors > instance dict > non-data descriptors > class dict. Applications: @property (descriptor returning function result), @classmethod/@staticmethod, Django ORM fields, lazy attributes, type checking, logging attribute access. Example: class ValidatedAttribute with __set__ validating values. Descriptors power Python's object system - methods are non-data descriptors binding functions to instances.
42 Explain lock-free programming and compare-and-swap operations.
Hard
Explain lock-free programming and compare-and-swap operations.
Lock-free algorithms ensure at least one thread makes progress, avoiding blocking. Core primitive: CAS (Compare-And-Swap) - atomically update if current value matches expected. Java: AtomicInteger.compareAndSet(), VarHandle. C++: std::atomic, compare_exchange. Pattern: read current, compute new, CAS; retry on failure. ABA problem: value changes A->B->A; solution: version counters, hazard pointers. Benefits: no deadlocks, better scalability, interrupt-safe. Challenges: complexity, subtle bugs, memory ordering (acquire/release semantics). Use cases: concurrent queues, counters, reference counting. Consider: is lock contention actually the bottleneck?
43 Explain the C++ memory model and memory ordering constraints.
Hard
Explain the C++ memory model and memory ordering constraints.
C++11 memory model defines how threads observe writes from other threads. Memory orderings: seq_cst (strongest, default - total order), acquire (reads after this see writes before release), release (writes before this visible after acquire), relaxed (no ordering guarantees, only atomicity). acquire-release: synchronizes between threads. seq_cst for safety, relaxed for performance-critical counters. memory_order_consume (rarely used). Fences: atomic_thread_fence for explicit barriers. Hardware: strong ordering (x86) vs weak (ARM). Use: load(acquire), store(release) for typical producer-consumer. Profile before weakening ordering.
44 Explain the JavaScript event loop and task queues in detail.
Hard
Explain the JavaScript event loop and task queues in detail.
Event loop enables async operations in single-threaded JS. Components: call stack (sync execution), Web APIs/Node APIs (async operations), callback queues. Macrotasks: setTimeout, setInterval, I/O, setImmediate (Node). Microtasks: Promise.then, queueMicrotask, MutationObserver. Loop cycle: execute stack, process ALL microtasks, render (browsers), ONE macrotask, repeat. Microtasks processed before next macrotask - can starve macrotasks. Node: additional phases (timers, poll, check). Understanding prevents: stack overflow, UI blocking, race conditions. async/await: syntactic sugar, still uses microtask queue.
45 Explain the Visitor, Strategy, and Observer patterns with use cases.
Hard
Explain the Visitor, Strategy, and Observer patterns with use cases.
Visitor: separate algorithm from object structure. Elements accept visitors that perform operations. Use: compilers (AST operations), report generation. Avoids modifying element classes. Strategy: define family of interchangeable algorithms. Context holds strategy reference, delegates execution. Use: payment processing, sorting strategies, validation rules. Runtime algorithm selection. Observer: one-to-many dependency; subjects notify observers of state changes. Use: event systems, MVC, reactive programming. Decouples subjects from observers. All three follow Open/Closed principle - add new behavior without modifying existing classes.
46 Explain Python's import system and how modules are loaded.
Hard
Explain Python's import system and how modules are loaded.
Import process: check sys.modules cache, find module (finders), load module (loaders). Finders: meta_path finders (first), path_based (sys.path). Built-in finder, frozen finder, path finder. Module types: built-in, frozen, packages, namespace packages. __import__ underlies import statement. importlib for programmatic imports. Circular imports: avoided if imports at function level or import module (not from). Package __init__.py executed on import. __all__ controls 'from X import *'. Relative imports in packages. Loader creates module object, exec module code. sys.path_hooks for custom loaders.
47 Compare static and dynamic typing, and gradual typing systems.
Hard
Compare static and dynamic typing, and gradual typing systems.
Static typing (Java, C++, Go): types checked at compile time. Benefits: early error detection, IDE support, optimization. Cost: verbosity, less flexibility. Dynamic typing (Python, JavaScript, Ruby): types checked at runtime. Benefits: flexibility, rapid development, duck typing. Cost: runtime errors, less tooling. Gradual typing (TypeScript, Python type hints, Flow): optional static types layered on dynamic language. Best of both: type where beneficial, dynamic where flexible. Type inference: compiler deduces types (Kotlin, Swift, TypeScript). Structural vs nominal: TypeScript structural, Java nominal. Trade-off: safety vs flexibility vs developer experience.
48 Explain Java Virtual Threads (Project Loom) and their impact.
Hard
Explain Java Virtual Threads (Project Loom) and their impact.
Virtual threads (Java 21): lightweight threads managed by JVM, not OS. Millions of virtual threads possible vs thousands of platform threads. Syntax: Thread.startVirtualThread(), Executors.newVirtualThreadPerTaskExecutor(). Continuation-based: virtual thread yields on blocking operations, carrier thread runs other virtual threads. Benefits: simple blocking code at scale, no reactive complexity. Use cases: high-concurrency I/O (web servers, database access). Considerations: don't pool virtual threads, avoid pinning (synchronized, native code), thread-local usage. Structured concurrency: StructuredTaskScope for managing related threads. Game-changer for concurrent Java applications.
49 Explain C++20 Concepts and how they improve templates.
Hard
Explain C++20 Concepts and how they improve templates.
Concepts are named constraints on template parameters, replacing SFINAE and enable_if. Syntax: template<typename T> concept Sortable = requires(T a) { a < a; }. Usage: template<Sortable T> or requires clause. Standard concepts: std::integral, std::floating_point, std::copyable, std::range. Benefits: clearer intent, better error messages, overload resolution. Requires expressions: test expressions, type requirements, compound requirements. Subsumption: more constrained overload preferred. Concepts enable: cleaner API documentation, constraint-based overloading, concept-based polymorphism. Major improvement for generic programming readability and usability.
50 Compare runtime characteristics of JVM, V8, and CPython.
Hard
Compare runtime characteristics of JVM, V8, and CPython.
JVM (Java, Kotlin, Scala): JIT compilation (C1, C2, GraalVM), optimizing compiler, ahead-of-time possible, sophisticated GC (G1, ZGC), strong optimization (inlining, escape analysis, devirtualization). Startup overhead, warm-up time. V8 (JavaScript, Node.js): multi-tier JIT (Ignition interpreter, TurboFan JIT), hidden classes for optimization, inline caching, concurrent GC. Fast startup, optimizes hot paths. CPython (Python): interpreted (compiles to bytecode), no JIT (PyPy has JIT), GIL limits parallelism, simple reference counting + cycle collector. Alternatives: PyPy (JIT), Cython (compile to C). Each optimized for different trade-offs: JVM for long-running servers, V8 for quick response, CPython for simplicity.