ProMind
SearchFor TeachersFor Parents
ProMind
Privacy PolicyTerms of ServiceRefund Policy

© 2025 DataGrid Softwares LLP. All rights reserved.

    Methods

    Flashcards for topic Methods

    Intermediate56 cardsGeneral

    Preview Cards

    Card 1

    Front

    When is it appropriate not to make defensive copies of mutable parameters in Java methods?

    Back

    Defensive copying can be omitted in these specific circumstances:

    1. When there's an explicit trust relationship:

      • Class and client are in the same package
      • Class documentation explicitly states caller must not modify parameters
    2. When the method/constructor indicates an explicit "handoff" of the object referenced by a parameter

      • The caller explicitly transfers ownership of the object to the method
    3. When there are significant performance concerns and the overhead of defensive copying is problematic

      • This should be clearly documented as a requirement for callers
    4. When using immutable parameters (preferred solution where possible)

    Note: Even when omitting defensive copies, document the expectations clearly to prevent invariant violations.

    Card 2

    Front

    What are the potential failure modes when a method doesn't properly validate its parameters, and how do they escalate in severity?

    Back

    Parameter validation failures escalate in severity (from least to most severe):

    1. Quick obvious failure: Method fails with a relevant exception at the beginning

      • Easy to debug, fails fast with clear cause
    2. Confusing exception: Method fails with unrelated exception during processing

      • Harder to debug, exception doesn't clearly indicate invalid parameter
    3. Silent incorrect result: Method completes but returns wrong result

      • Very dangerous, calculation appears successful but is actually wrong
    4. Corrupted state: Method completes but leaves object in inconsistent state

      • Most dangerous, causes errors at unrelated points in the future
      • Violates failure atomicity
      • May corrupt persistent data

    The severity increases based on:

    • How far from the root cause the symptom appears
    • How difficult it becomes to trace the problem
    • How much damage can be done before detection

    Always validate parameters early to prevent escalation to more severe failure modes.

    Card 3

    Front

    What problematic behavior occurs when autoboxing interacts with method overloading, particularly with the List interface's remove methods?

    Back

    • List<E> has two overloaded remove methods that can cause confusion:

      • remove(E): Removes an element matching the value
      • remove(int): Removes element at a specific position
    • When using primitive int with lists of Integer:

      • list.remove(i) selects remove(int) removing by position
      • list.remove((Integer)i) selects remove(E) removing by value
    • Example of confusing behavior:

    List<Integer> list = new ArrayList<>(Arrays.asList(-3, -2, -1, 0, 1, 2)); for (int i = 0; i < 3; i++) { list.remove(i); // Removes elements at positions 0, 1, 2 (not values 0, 1, 2) } // Result: [-2, 0, 2] (not [-3, -2, -1] as might be expected)
    • Fix: Cast to Integer or use valueOf:
    list.remove((Integer) i); // or list.remove(Integer.valueOf(i));
    Card 4

    Front

    What API design advice is given for method naming and method count in an interface or class?

    Back

    • Method Naming Guidelines:

      • Always follow standard naming conventions
      • Choose understandable names consistent with other names in the same package
      • Aim for consistency with broader consensus (e.g., Java library APIs)
      • Avoid long method names
      • Look to Java library APIs for guidance
    • Method Count Principle: "Every method should pull its weight"

      • Too many methods make a class difficult to:
        • Learn
        • Use
        • Document
        • Test
        • Maintain
      • For interfaces, too many methods burden implementors
    • Guidelines for Adding Methods:

      • For each action, provide one fully functional method
      • Only add "shorthand" convenience methods if they'll be frequently used
      • When in doubt, leave it out
      • Consider using different names for methods rather than overloading
        • Example: writeBoolean(), writeInt(), writeLong() instead of overloaded write()
    • ObjectOutputStream Example: Has different method names for each type instead of overloading:

    void writeBoolean(boolean v); void writeInt(int v); void writeLong(long v); // Instead of overloaded write(boolean), write(int), write(long)
    Card 5

    Front

    What is the recommended safe, conservative policy for method overloading to avoid potential confusion?

    Back

    • Core Conservative Policy: Never export two overloadings with the same number of parameters

    • For Varargs Methods: Do not overload varargs methods at all (with few exceptions)

    • Rationale: Ensures programmers are never in doubt about which overloading applies to any set of parameters

    • Alternative Approach: Use different method names instead of overloading

      • Example: Instead of write(int), write(long), etc.
      • Use writeInt(int), writeLong(long), etc.
    • Special Case for Constructors:

      • Constructors must be overloaded (can't have different names)
      • Consider using static factory methods as an alternative
      • With constructors, you don't need to worry about interactions between overloading and overriding
    • Lambda Method Reference Issues:

      • Java 8 lambdas and method references increased overloading confusion
      • Example issue:
      // This works: new Thread(System.out::println).start(); // This doesn't compile: exec.submit(System.out::println); // Ambiguous between Runnable and Callable
    Card 6

    Front

    When using varargs in performance-critical code, what optimization technique can be applied when most calls use a small number of arguments?

    Back

    For performance-critical varargs methods where most calls use few arguments:

    1. Create specific overloaded methods for the common cases (0-3 arguments)
    2. Use varargs only for the less common case with more arguments
    public void foo() { /* implementation */ } public void foo(int a1) { /* implementation */ } public void foo(int a1, int a2) { /* implementation */ } public void foo(int a1, int a2, int a3) { /* implementation */ } public void foo(int a1, int a2, int a3, int... rest) { /* implementation for 4+ arguments */ }

    This optimization:

    • Avoids array allocation and initialization cost (every varargs call creates an array)
    • Reserves the varargs overhead only for the uncommon cases (e.g., the 5% of calls with 4+ arguments)
    • Is used by core Java libraries like EnumSet's static factories
    • Should only be applied after performance measurement confirms the need

    Remember: This is a performance optimization and should only be used when necessary.

    Card 7

    Front

    What is an "inexact method reference" in Java, and why does it cause problems with overloaded methods?

    Back

    An inexact method reference:

    • Is a method reference like System.out::println that could potentially refer to multiple overloaded methods
    • Its precise target cannot be determined until used in a context with a specific functional interface type
    • Is "inexact" because the compiler doesn't know which overloaded version to select without context

    Problems with overloaded methods:

    1. During overload resolution, inexact method references are ignored by applicability tests
    2. The compiler cannot determine which functional interface target type to select
    3. This creates confusing scenarios where code that "should" compile doesn't

    Example demonstrating the problem:

    // These two methods accept different functional interfaces void process(Consumer<Object> c) { /* implementation */ } void process(Predicate<Object> p) { /* implementation */ } // This fails to compile even though it seems like it should work process(System.out::println); // ERROR - ambiguous // These work fine because the lambda form provides context process(x -> System.out.println(x)); // Calls process(Consumer) process(x -> {System.out.println(x); return true;}); // Calls process(Predicate)

    This is a classic case where the overload resolution algorithm works differently than most developers would expect.

    Card 8

    Front

    What technique should you use to ensure that overloaded methods with similar functionality behave identically when passed the same parameters?

    Back

    To ensure consistent behavior across overloaded methods:

    Use forwarding - have the more specific method forward to the more general method:

    // Ensuring identical behavior by forwarding public boolean contentEquals(StringBuffer sb) { // Forward from specific to general implementation return contentEquals((CharSequence) sb); } public boolean contentEquals(CharSequence cs) { // Primary implementation here // ...implementation logic... }

    This technique:

    1. Centralizes logic in one place (the more general method)
    2. Eliminates duplication that could lead to inconsistencies
    3. Makes maintenance easier - changes only need to be made in one place
    4. Ensures that identical input always produces identical output regardless of which overload is called
    5. Preserves type-specific method signatures for backward compatibility

    A common use case is when retrofitting existing classes to implement new interfaces or when evolving an API while maintaining backwards compatibility.

    Card 9

    Front

    How should you properly document the preconditions and postconditions of a method in Javadoc, and what is the relationship between @throws tags and preconditions?

    Back

    Documenting Preconditions and Postconditions:

    Preconditions: Conditions that must be true before a method is called

    • Document in @param tags for affected parameters
    • Document in @throws tags for unchecked exceptions
    • May specify in the method description

    Postconditions: Conditions guaranteed to be true after method execution

    • Document in the method description
    • Document in @return tag

    Example:

    /** * Returns a substring of this string, starting at the specified index * and extending to the end of the string. * * @param beginIndex the beginning index, inclusive; must be non-negative * and less than or equal to the length of this string * @return the specified substring * @throws IndexOutOfBoundsException if {@code beginIndex} is negative or * greater than the length of this string */ public String substring(int beginIndex) { ... }

    Relationship between @throws and preconditions:

    • Unchecked exceptions (@throws) document precondition violations
    • Each @throws tag for an unchecked exception should:
      1. State precisely what conditions trigger the exception
      2. Use the form "if..." followed by the violation condition
      3. Include code sample in {@code} tags when condition is complex

    Best practices:

    • Be explicit about nullability requirements
    • Document side effects (observable state changes)
    • Use specific language for mutability guarantees
    • Specify thread safety expectations
    Card 10

    Front

    How should you document module-level elements when using the Java module system?

    Back

    When using the Java module system (introduced in Java 9):

    1. Place module-level documentation comments in the module-info.java file
    2. Format the comments using the standard Javadoc comment style
    3. Document the module's purpose, exported packages, and service providers
    4. Include information about module dependencies when relevant

    Example:

    /** * A module providing core utility classes for the application. * <p> * This module exports various utility packages and provides * implementations of the logging service. */ module com.example.utilities { exports com.example.utilities.collections; exports com.example.utilities.concurrency; provides java.util.logging.LoggingProvider with com.example.utilities.logging.LogProvider; }

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