ProMind
SearchFor TeachersFor Parents
ProMind
Privacy PolicyTerms of ServiceRefund Policy

© 2025 DataGrid Softwares LLP. All rights reserved.

    General Programming

    Flashcards for topic General Programming

    Intermediate44 cardsGeneral

    Preview Cards

    Card 1

    Front

    Why is Math.abs(rnd.nextInt()) % n a deeply flawed approach for generating random numbers in a range?

    Back

    The Math.abs(rnd.nextInt()) % n approach has three critical flaws:

    1. Poor distribution: If n is not a power of 2, some numbers will appear more frequently than others. For example, with the code, approximately 2/3 of generated numbers will fall in the lower half of the range.

    2. Short period for small ranges: If n is a small power of two, the sequence will repeat after a relatively short period.

    3. Out-of-range error: If nextInt() returns Integer.MIN_VALUE, Math.abs() will also return Integer.MIN_VALUE (due to two's complement arithmetic), and the modulo operation can produce a negative result.

    Instead, use standard library methods:

    // For single-threaded contexts (Java 7+) ThreadLocalRandom.current().nextInt(0, n); // Exclusive upper bound // For parallel streams or fork-join pools SplittableRandom random = new SplittableRandom(); random.nextInt(0, n); // Exclusive upper bound
    Card 2

    Front

    What makes for-each loops superior to traditional for loops, and what are the specific scenarios where you cannot use for-each loops?

    Back

    Advantages of for-each loops:

    • Eliminates clutter of iterator/index variables
    • Reduces opportunities for error (iterator appears only once)
    • Applies uniformly to collections and arrays
    • Especially beneficial for nested iteration (prevents copy-paste errors)
    • Improves readability and conciseness
    • No performance penalty

    Scenarios where for-each loops cannot be used:

    1. Destructive filtering: When you need to remove elements during iteration

      // Must use explicit iterator for removal for (Iterator<Element> i = c.iterator(); i.hasNext(); ) { Element e = i.next(); if (shouldRemove(e)) { i.remove(); // Cannot access remove() with for-each } } // Alternative in Java 8+: c.removeIf(e -> shouldRemove(e));
    2. Transforming: When you need to replace elements in a collection/array

      // Need index/iterator to modify collection for (int i = 0; i < list.size(); i++) { list.set(i, transform(list.get(i))); }
    3. Parallel iteration: When you need to traverse multiple collections simultaneously

      // Need explicit control of both iterators for (Iterator<A> i = a.iterator(), j = b.iterator(); i.hasNext() && j.hasNext(); ) { processSimultaneously(i.next(), j.next()); }
    Card 3

    Front

    What is the optimal technique for minimizing scope in loops that involve expensive computations in their termination conditions?

    Back

    The optimal technique is to use a "hoisted" double variable declaration in the for loop initialization:

    // Efficient loop with hoisted limit computation for (int i = 0, n = expensiveComputation(); i < n; i++) { // Do something with i }

    Key benefits:

    1. The expensive computation is performed exactly once
    2. Both variables (i and n) have the minimum required scope
    3. The scope is limited to exactly the region where they're needed
    4. Avoids redundant computation on each iteration

    This pattern should be used whenever:

    • The loop termination check involves a method call
    • The computation is guaranteed to return the same result each time
    • The computation is potentially expensive

    This technique provides both a performance optimization and scope minimization in a single solution.

    Card 4

    Front

    Explain the specific dangers when a local variable is declared prematurely (before it's used) in Java code.

    Back

    Premature variable declaration creates several dangerous problems:

    1. Scope expansion: The variable remains visible beyond its intended usage region

      String value; // Premature declaration if (condition) { value = "something"; // Use value appropriately here } // value is still in scope here, creating possible misuse opportunities
    2. Unintentional use: Variables may be accidentally used before initialization

      int x; // Declared but not initialized // Complex logic... x++; // Accidental use before initialization - compiler error
    3. Cognitive burden: Readers must remember the type and purpose of the variable between declaration and first use

    4. Initialization delay: Proper initialization may be forgotten or incorrectly performed

    5. Stale references: Objects remain referenced longer than necessary, potentially delaying garbage collection

    The proper approach is:

    // In the original scope if (condition) { String value = "something"; // Declared precisely where needed // Use value } // value goes out of scope exactly when no longer needed
    Card 5

    Front

    What problematic design pattern can occur when using while loops for iteration, and why does this pattern lead to bugs that might be difficult to detect?

    Back

    The problematic pattern with while loops is the "iterator leakage" anti-pattern:

    // Problematic while loop pattern Iterator<Element> i = c.iterator(); while (i.hasNext()) { doSomething(i.next()); } ... // Later in code Iterator<Element> i2 = c2.iterator(); // New iterator while (i.hasNext()) { // BUG! Using original iterator 'i' instead of 'i2' doSomethingElse(i2.next()); }

    This pattern is dangerous because:

    1. The iterator variable remains in scope after the first loop completes
    2. Copy-paste errors can easily reference the wrong iterator variable
    3. The code compiles without errors (silent bug)
    4. The program runs without exceptions but produces incorrect results
    5. The second loop may terminate immediately (if first iterator is exhausted)
    6. The bug gives the false impression that the second collection is empty

    Why it's hard to detect:

    • No compiler errors or runtime exceptions
    • Produces plausible but incorrect output
    • May occur sporadically depending on collection sizes
    • The error lies in the loop condition, not in the more visible loop body

    For-each loops eliminate this issue entirely by limiting the scope of iteration variables:

    // For-each loops prevent this bug completely for (Element e : c) { doSomething(e); } for (Element e : c2) { // Completely separate variable scope doSomethingElse(e); }
    Card 6

    Front

    What are the most effective techniques for minimizing the scope of local variables in Java, and how do they specifically improve code quality?

    Back

    Techniques for Minimizing Variable Scope:

    1. Declare variables at point of first use

      // Instead of declaring at method start void process() { // Only declare when needed for (Element e : collection) { String formatted = e.toString(); // Declared exactly when needed // Use formatted } }
    2. Prefer for loops over while loops

      // For loop constrains iterator scope for (Iterator<Element> i = c.iterator(); i.hasNext(); ) { Element e = i.next(); // i and e only exist in this block }
    3. Use for-each loops whenever possible

      // Cleanest approach with minimum scope for (Element e : elements) { // e only exists here }
    4. Create small, focused methods

      // Split large methods into smaller ones void process() { loadData(); transformData(); saveResults(); }
    5. Use hoisted loop limit calculations

      for (int i = 0, n = expensiveComputation(); i < n; i++) { // Both i and n have minimum scope }

    Benefits to Code Quality:

    1. Reduced Cognitive Load: Readers only need to track variables relevant to current code section
    2. Lower Error Rate: Variables can't be accessed outside their intended region
    3. Improved Maintainability: Changes to one section won't accidentally affect others
    4. Better Compiler Optimization: Smaller scopes enable more aggressive JIT optimizations
    5. Earlier Garbage Collection: Objects referenced by local variables are eligible for GC sooner
    6. Prevention of Stale Variable Reuse: Variables can't be accidentally reused after their intended lifetime
    7. Self-Documenting Code: Variable locations indicate their purpose and usage window
    Card 7

    Front

    What are the key considerations when choosing between BigDecimal, int, and long for monetary calculations?

    Back

    Choosing between number types for monetary calculations:

    BigDecimal:

    • Advantages:
      • Provides exact decimal arithmetic
      • Allows full control over rounding (8 different rounding modes)
      • Handles arbitrary precision
      • Ideal for legally mandated financial calculations
    • Disadvantages:
      • More verbose than primitive types
      • Significantly slower than primitives
      • Must use String constructor (not double constructor) to avoid precision issues
      // Correct: uses String constructor BigDecimal value = new BigDecimal("10.25"); // Incorrect: introduces floating-point imprecision BigDecimal value = new BigDecimal(10.25);

    int/long:

    • Advantages:
      • Simple and fast
      • Sufficient for most practical monetary calculations
      • Easy to understand
    • Disadvantages:
      • Requires manual decimal point tracking (typically calculate in cents/smallest unit)
      • Limited range (int: ±2.1 billion, long: ±9.2 quintillion)

    Selection guidelines:

    • Use int if amounts won't exceed 9 decimal digits
    • Use long if amounts won't exceed 18 decimal digits
    • Use BigDecimal if amounts might exceed 18 digits or when exact rounding control is needed
    • For performance-critical code with moderate precision needs, use int/long
    Card 8

    Front

    What is the optimal implementation of a ThreadLocal that addresses all the shortcomings of the string-based and capability-based approaches?

    Back

    A parameterized class that combines type safety with instance methods:

    public final class ThreadLocal<T> { public ThreadLocal(); public void set(T value); public T get(); }

    This implementation:

    • Eliminates the global namespace problem
    • Provides compile-time type safety through generics
    • Removes the need for casting when retrieving values
    • Makes the API more intuitive by making operations instance methods
    • Is faster and more elegant than key-based approaches
    • Matches the actual implementation in java.lang.ThreadLocal
    Card 9

    Front

    What are the legitimate cases where it's appropriate to use a class rather than an interface as a reference type?

    Back

    Three legitimate cases:

    1. Value classes with no corresponding interfaces
      • Examples: String, BigInteger
      • These classes are often final with no alternative implementations
    2. Classes from frameworks with class-based fundamental types
      • When the framework uses abstract base classes instead of interfaces
      • Example: java.io classes like OutputStream
      • Use the most general base class that provides required functionality
    3. Classes that implement interfaces but provide extra methods
      • When code relies on methods not in the interface
      • Example: PriorityQueue.comparator() method not in Queue interface
      • Should be very rare - indicates potential design issues

    General rule: Always use the least specific type in the hierarchy that provides the required functionality.

    Card 10

    Front

    What are the three primary disadvantages of using reflection?

    Back

    1. Loss of compile-time type checking
      • Type errors become runtime exceptions rather than compile-time errors
      • Exception checking happens at runtime
      • Nonexistent or inaccessible methods fail only when invoked
    2. Verbose and clumsy code
      • Reflection requires lengthy code for simple operations
      • Code becomes tedious to write and difficult to read
      • Same operations that take one line normally require dozens with reflection
    3. Significant performance penalty
      • Reflective method invocation is substantially slower
      • Can be 10+ times slower than direct invocation
      • Example: a method with no parameters and int return was measured to be 11× slower when invoked reflectively

    These disadvantages make reflection suitable only for specific use cases where the flexibility is absolutely required.

    Showing 10 of 44 cards. Add this deck to your collection to see all cards.