Back to I/O & System
Q1Question 1 of 3

What is the difference between System.out, System.err, and System.in?

Key Concepts
  • System.out: standard output stream (PrintStream) – used for normal output
  • System.err: standard error stream (PrintStream) – used for error messages, unbuffered
  • System.in: standard input stream (InputStream) – reads user input from console
  • out and err both go to the console by default but are separate streams
  • In production, use a logging framework (SLF4J/Logback) instead of System.out

Definition

System.out prints normal output, System.err prints error output (unbuffered), and System.in reads input from the console. In production, use a logging framework instead.

Three standard streams:

  • System.out – standard output (PrintStream). Buffered. For normal program output.
  • System.err – standard error (PrintStream). Unbuffered (prints immediately). For error/warning messages.
  • System.in – standard input (InputStream). Raw byte stream from the keyboard. Wrap with Scanner for easy reading.

System.out is the bank's normal receipt printer. System.err is the alarm printer that prints immediately. System.in is the keypad where the customer types their PIN.

Understanding the Concepts

Usage

JAVA
System.out.println("Transfer complete: Rs.50000");  // normal output
System.err.println("ERROR: insufficient funds");    // error output (unbuffered)

// Reading input
Scanner scanner = new Scanner(System.in);
System.out.print("Enter account ID: ");
String id = scanner.nextLine();

Redirecting streams

BASH
# Redirect output to a file, errors stay on console
java TransferApp > output.log 2>&1

# Separate output and error
java TransferApp > output.log 2> error.log

In production, use a logger

JAVA
// BAD: System.out in production code
System.out.println("Transfer done");

// GOOD: use SLF4J/Logback
private static final Logger log = LoggerFactory.getLogger(TransferService.class);
log.info("Transfer done: from={} to={} amount={}", fromId, toId, amount);

Loggers provide levels (DEBUG, INFO, WARN, ERROR), formatting, file rotation, and structured output.

What are common mistakes?

A common mistake is not understanding the concept fully before using it in production banking applications.

Wrong approach:

JAVA
package com.bank.service;

public class TransferService {
    public void transfer(String fromAccount, String toAccount, double amount) {
        // WRONG: using double for money
        double balance = getBalance(fromAccount);
        balance = balance - amount;
    }
    private double getBalance(String id) { return 10000.0; }
}

Correct approach:

JAVA
package com.bank.service;

import java.math.BigDecimal;

public class TransferService {
    public void transfer(String fromAccount, String toAccount, BigDecimal amount) {
        // CORRECT: using BigDecimal for money
        BigDecimal balance = getBalance(fromAccount);
        balance = balance.subtract(amount);
    }
    private BigDecimal getBalance(String id) { return new BigDecimal("10000.00"); }
}

Always use BigDecimal for monetary calculations in banking systems to avoid floating-point precision errors.

What should a senior engineer know?

A senior engineer working on banking systems should understand the production implications of this concept.

  • Performance impact. Measure with JMH before making assumptions about which approach is faster.
  • Thread safety. In a multi-threaded banking service processing concurrent transactions, always consider whether the approach is thread-safe.
  • Memory footprint. Use JFR and VisualVM to measure actual memory usage under realistic banking workloads.
  • Monitoring. Set up JMX metrics and alerts for production banking applications.
JAVA
package com.bank.monitoring;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;

public class MemoryMonitor {
    public static void printMemoryUsage() {
        MemoryMXBean mem = ManagementFactory.getMemoryMXBean();
        System.out.println("Heap: " + mem.getHeapMemoryUsage());
        System.out.println("Non-Heap: " + mem.getNonHeapMemoryUsage());
    }
}

What are the edge cases?

Edge cases can cause unexpected behavior in banking applications. Here are some to watch for.

JAVA
package com.bank.edge;

public class EdgeCaseDemo {
    public static void main(String[] args) {
        // Edge case 1: null handling
        String accountId = null;
        try {
            System.out.println(accountId.length());
        } catch (NullPointerException e) {
            System.out.println("Null account ID");
        }

        // Edge case 2: empty vs null
        String emptyId = "";
        System.out.println(emptyId.isEmpty());  // true
        System.out.println(emptyId == null);     // false

        // Edge case 3: boundary values
        java.math.BigDecimal zero = java.math.BigDecimal.ZERO;
        java.math.BigDecimal negativeBalance = new java.math.BigDecimal("-0.01");
        System.out.println(zero.compareTo(negativeBalance) > 0);  // true
    }
}
TEXT
Null account ID
true
false
true

Always test with null values, empty strings, boundary values, and negative amounts in banking applications.

What are common interview follow-up questions?

Interviewers often follow up with these related questions:

  • How does this concept apply to a high-throughput banking transaction system?
  • What are the performance implications in a production environment?
  • How would you debug issues related to this concept?
  • What tools would you use to monitor this in production?
  • How does this behave differently in Java 8 vs Java 17+?

When answering follow-up questions, always relate your answer back to practical experience. For example, at National Bank of India, Rajesh debugged a production issue related to this concept by using JFR recordings and heap dumps. Providing concrete examples from banking systems shows the interviewer that you understand both the theory and the practice.

Visual Overview

DIAGRAM
  System.out  → stdout → console (buffered)
  System.err  → stderr → console (unbuffered, prints immediately)
  System.in   → stdin  → keyboard input

  Production: use SLF4J + Logback instead of System.out

Key Takeaway

System.out is for normal output, System.err is for errors (prints immediately), and System.in reads keyboard input. In production, replace System.out with a proper logging framework.

One sentence to remember: out for output, err for errors (unbuffered), in for input – use a logger in production.

---

Share
Use ← → arrow keys to navigate