1. Match use-cases correctly:
final modifies classes/methods/variables; finally executes regardless of exception; finalize() is legacy GC callback (discouraged).
Get the Preplance app for a seamless learning experience. Practice offline, get daily streaks, and stay ahead with real-time interview updates.
Get it on
Google Play
4.9/5 Rating on Store
TCS · Java
Practice Java questions specifically asked in TCS interviews – ideal for online test preparation, technical rounds and final HR discussions.
Questions
37
Tagged for this company + subject
Company
TCS
View company-wise questions
Subject
Java
Explore topic-wise practice
Go through each question and its explanation. Use this page for targeted revision just before your TCS Java round.
final modifies classes/methods/variables; finally executes regardless of exception; finalize() is legacy GC callback (discouraged).
For complete preparation, combine this company + subject page with full company-wise practice and subject-wise practice. You can also explore other companies and topics from the links below.
Encapsulation (data safety), Abstraction (hide detail), Inheritance (reuse), Polymorphism (flexible behavior).
LSP requires subtypes to be usable anywhere the base is expected without breaking semantics.
They define stable boundaries—hiding internals (private), exposing minimal extension points (protected), and clear public APIs—reducing coupling and easing evolution.
The pool enables reuse of identical String literals, saving memory and speeding equality checks.
equals is overridden to compare character content; == checks object identity.
HashSet (no order), LinkedHashSet (insertion order), TreeSet (sorted).
Overloading resolved at compile-time; overriding at runtime via dynamic dispatch.
Overridden instance methods are chosen by the actual object type at runtime.
Create a checked exception to force callers to acknowledge a recoverable domain error—like a business rule violation or a missing required configuration. Create an unchecked exception when the failure indicates a programmer mistake or an unexpected state that typical callers cannot handle—like illegal arguments, null misuses, or invariant violations. Use descriptive names and include context in the message.
HashMap maintains a linked list per bucket; when collisions make a bucket long (e.g., ≥8) and capacity is sufficient, it treeifies that bucket into a red-black tree. This improves worst-case lookups from O(n) to O(log n).
Inheritance models an is-a relationship; composition/aggregation model has-a.
javac produces bytecode; the platform-specific JVM interprets/JIT-compiles it, enabling WORA.
Each thread has its own JVM stack containing frames for method execution.
Encapsulation bundles state and behavior, typically with private fields and public getters/setters.
Abstract classes: partial implementation + state; interfaces: contracts of behavior; since Java 8+, interfaces can have default/static methods but no instance state.
It returns an unmodifiable view that throws on mutating operations.
Throwable is the root. It has two direct children: Error and Exception. RuntimeException extends Exception. Errors are siblings of Exception, not children of RuntimeException.
Use @ControllerAdvice with @ExceptionHandler methods to map exceptions to structured error responses. Return a stable JSON envelope with fields like timestamp, error code, message, and correlation ID. Map domain errors to 4xx with actionable messages; map unexpected faults to 5xx with a generic message and a trace ID. Always log server-side with the cause and context; never leak sensitive details in responses.
TreeMap uses natural ordering or a comparator; null keys cannot be compared and thus are not supported. Null values are allowed.
One: Impose a strict global lock ordering and acquire locks in that order everywhere. Two: Use tryLock with timeout and back off if you can’t acquire all locks. Other options: minimize lock scope, prefer immutable data, or replace coarse locks with higher-level concurrency utilities.
Unboxing a null Integer to int throws NPE; wrappers are immutable and live on heap.
Use Comparable when a class has a natural, single ordering—like String or BigDecimal—and you control the source to implement compareTo. Prefer Comparator when you need multiple orderings (e.g., by name, then by date) or you can’t modify the class. Comparator keeps sorting logic separate and flexible.
ExecutorService abstracts thread creation. You submit tasks, not threads; it reuses a pool, limits concurrency, offers futures for results, and supports graceful shutdown. This improves throughput and stability.
ReentrantLock provides advanced features: timed/interruptible acquisition, optional fairness, and separate Lock/Condition objects. Performance depends on the workload; it’s not universally faster.
Phaser allows parties to register and deregister at runtime and supports multiple synchronization phases with custom phase-advance logic, making it a superset of many barrier patterns.
Call shutdown to reject new tasks and let running tasks finish. Await for a bounded time. If tasks still run, call shutdownNow to interrupt and drain the queue. This avoids leaks and dangling threads.
One: Measure first—enable GC logs and capture p99 latency and allocation rates. Two: Fix allocation hot spots—reduce temporary objects, reuse buffers, enable pooling only if profiling proves it. Three: Right-size the heap and young generation to match live-set and allocation rate. Four: Set realistic pause goals (e.g., G1 MaxGCPauseMillis) and re-measure. Only then consider switching collectors (e.g., to ZGC) if goals still aren’t met.
Metaspace holds class metadata (replacing PermGen). A common growth cause is classloader leaks—dynamically loading classes without unloading their defining classloader, often seen in hot-reloaded apps or container redeploys. Each leaked classloader pins its classes and metadata, expanding Metaspace.
Lambdas close over effectively final variables, just like anonymous classes. They do not require generating a new class per use and can target any compatible functional interface.
`collect` is built for mutable result containers and supports parallel-friendly accumulation and combination. `reduce` targets immutable, associative reductions.
Side effects (e.g., mutating external state in map/filter) break referential transparency, hinder parallelization, and cause subtle bugs. Prefer pure functions and let `collect` build results. If you must observe, use `peek` only for diagnostics; for imperative accumulation, a simple loop may be clearer.
Runnable separates the work from the execution mechanism, allowing reuse with pools and avoiding subclassing limits. You start a thread with start(), which calls run() internally. A terminated thread cannot be restarted.
Stream classes move raw bytes; Reader/Writer classes decode and encode characters using a charset. They’re not interchangeable, but bridges like InputStreamReader and OutputStreamWriter adapt bytes to characters and vice-versa.
JVM searches for a public static void main(String[]). Varargs are allowed but return must be void.
Class must override and can delegate to a specific interface’s default via Interface.super.method().
Releasing a monitor happens-before the subsequent acquire of that monitor by another thread. This ensures visibility of changes made inside the critical section.