JUnit测试checkFile方法遇StackOverflowError问题求助
Let's cut straight to the chase: your StackOverflowError is happening because of unbounded recursive calls in your error handling logic. Every time you hit an invalid file entry, duplicate ID, or missing file, you call sim.checkFile(...) again—this adds a new stack frame every time, and eventually the stack runs out of space. Even switching to BufferedReader won't fix this because the recursion is the root issue, not the I/O class you're using.
Since you can't add new methods, we need to refactor the recursive logic into a loop (which won't pile up stack frames) while keeping all your original validation rules intact. Here's how to fix it:
Step-by-Step Fixed Code
public ArrayList<Customer> checkFile(int stops, File file) { Simulator sim = new Simulator(); ArrayList<Customer> custList = new ArrayList<>(); boolean isValidFile = false; do { custList.clear(); // Reset list for each new file attempt List<Integer> idArray = new ArrayList<>(); int linesProcessed = 0; boolean hasError = false; // Use try-with-resources to auto-close Scanner and avoid leaks try (Scanner reader = new Scanner(file)) { while (reader.hasNextLine() && !hasError) { String customerdata = reader.nextLine(); String[] dataArray = customerdata.split(" "); int[] parsedVals = new int[4]; // Parse and validate each field for (int i = 0; i < dataArray.length; i++) { try { parsedVals[i] = Integer.parseInt(dataArray[i]); if (parsedVals[i] <= 0) { System.out.println("file input 0"); throw new IllegalArgumentException(); } if ((i == 2 || i == 3) && parsedVals[i] > stops) { throw new IllegalArgumentException(); } } catch (NumberFormatException ex) { System.out.println(linesProcessed == 0 ? "Each line must have four integers. Try again." : "Regular: Data in input file is not correct. Try again."); hasError = true; break; // Exit parsing loop early } catch (IllegalArgumentException args) { System.out.println("Data in input file is not correct. Try again."); hasError = true; break; // Exit parsing loop early } } if (hasError) break; // Skip rest of line processing // Validate start/stop floors are different try { if (parsedVals[2] == parsedVals[3]) { throw new IllegalArgumentException(); } custList.add(new Customer(parsedVals[0], parsedVals[1], parsedVals[2], parsedVals[3])); idArray.add(parsedVals[0]); linesProcessed++; } catch (IllegalArgumentException ex) { System.out.println("Data in input file is not correct. Try again."); hasError = true; break; } } // Check for duplicate IDs if no errors found yet if (!hasError) { boolean duplicates = false; for (int j = 0; j < idArray.size() && !duplicates; j++) { for (int k = j + 1; k < idArray.size(); k++) { // Use equals() for Integer comparison to avoid value range bugs if (idArray.get(k).equals(idArray.get(j))) { duplicates = true; break; } } } if (duplicates) { System.out.println("Duplicates: Data in input file is not correct. Try again."); hasError = true; } else { isValidFile = true; // File is valid, exit loop } } } catch (FileNotFoundException ex) { System.out.println("File not found, try again."); hasError = true; } // Get new file if current one is invalid, then restart the loop if (hasError) { file = sim.getInputFile(); } } while (!isValidFile); return custList; }
Key Changes Explained
- Replaced Recursion with a Loop: Instead of nesting stack frames with recursive calls, we use a
do-whileloop that restarts validation with a new file. This keeps the stack size constant, eliminating the overflow. - Try-With-Resources: The
Scanneris wrapped in a try-with-resources block to auto-close it after use—fixing resource leaks that could cause unexpected behavior over multiple attempts. - Early Error Exit: We use a
hasErrorflag to break out of processing loops as soon as an invalid entry is found, avoiding unnecessary work and messy control flow. - Clean State on Each Attempt: Variables like
custListandidArrayare reset every time we try a new file, ensuring no leftover data from previous attempts. - Fixed Integer Comparison: Switched from
==toequals()for checking duplicate IDs—using==onIntegerobjects can fail for values outside the -128 to 127 range.
Why This Fixes the StackOverflowError
By using a loop instead of recursion, we reuse the same stack frame for every file attempt. No matter how many invalid files the user provides, the stack won't grow indefinitely. This approach preserves all your original validation rules while complying with your "no new methods" requirement.
内容的提问来源于stack exchange,提问作者Steve Bien-Aime

