☕ Java
Console Input
The System.console() method returns a Console object that provides direct access to the character-based console (terminal) attached to the JVM. Its primary advantage over Scanner and BufferedReader is the readPassword() method, which reads input without echoing characters to the screen — essential for collecting passwords and other sensitive data securely.
The Console Class
System.console() returns the unique Console instance associated with the JVM, or null if the JVM is not connected to a console — which happens when input or output is redirected (e.g. in IDE run configurations, piped commands, or automated tests). Always null-check before using Console. Console is not available in most IDE environments during development.
Java
import java.io.Console;
public class ConsoleExample {
public static void main(String[] args) {
// ── Get the Console instance: ─────────────────────────────────
Console console = System.console();
// ── ALWAYS null-check — not available in all environments: ────
if (console == null) {
System.err.println("No console available.");
System.err.println("Run from a terminal, not from an IDE.");
System.exit(1);
}
// ── Read a line of text: ──────────────────────────────────────
String name = console.readLine("Enter your name: ");
System.out.println("Hello, " + name);
// ── Read formatted prompt: ────────────────────────────────────
String city = console.readLine("Enter city for %s: ", name);
System.out.println("City: " + city);
// ── Read an integer (readLine returns String — must parse): ───
int age = Integer.parseInt(
console.readLine("Enter age: ").trim());
System.out.println("Age: " + age);
// ── Write to console: ─────────────────────────────────────────
console.printf("Welcome, %s from %s!%n", name, city);
console.writer().println("Using the console writer.");
console.flush();
}
}readPassword() — Secure Input
readPassword() reads input without displaying the characters on screen — the terminal echoing is disabled for the duration of the call. It returns a char[] rather than a String. This is intentional: String objects are immutable and remain in memory until garbage collected, while a char[] can be explicitly zeroed out immediately after use, reducing the window during which the password exists in memory.
Java
import java.io.Console;
import java.util.Arrays;
public class SecurePasswordInput {
public static void main(String[] args) {
Console console = System.console();
if (console == null) {
System.err.println("No console — run from terminal.");
return;
}
// ── Read password — characters not echoed to screen: ─────────
char[] password = console.readPassword("Enter password: ");
// User types their password — nothing appears on screen
// ── Use the password (validate, hash, etc.): ──────────────────
boolean valid = validatePassword(password);
// ── CRITICAL: zero out the password array immediately after use: ─
Arrays.fill(password, ' ');
// password array now contains all null characters
// The actual password value no longer exists in memory
if (valid) {
console.printf("Login successful.%n");
} else {
console.printf("Invalid password.%n");
}
}
private static boolean validatePassword(char[] input) {
char[] correct = "secret123".toCharArray();
boolean match = Arrays.equals(input, correct);
Arrays.fill(correct, ' '); // zero out the reference too
return match;
}
}
// ── readPassword with formatted prompt: ──────────────────────────────
char[] pwd = console.readPassword("Password for %s: ", username);
// ── Why char[] instead of String: ────────────────────────────────────
//
// String password = new String(console.readPassword(...));
//
// Problems with String:
// 1. Strings are immutable — cannot be overwritten in memory
// 2. String may be interned in the String pool
// 3. Remains in heap until GC decides to collect it
// 4. May appear in heap dumps, thread dumps, or logs
//
// char[] solution:
// 1. Can be zeroed: Arrays.fill(pwd, ' ')
// 2. Password window in memory is minimised
// 3. Standard security practice (recommended by OWASP)
// ── Confirm password example: ────────────────────────────────────────
Console con = System.console();
char[] pwd1 = con.readPassword("New password: ");
char[] pwd2 = con.readPassword("Confirm password: ");
if (Arrays.equals(pwd1, pwd2)) {
con.printf("Password set successfully.%n");
} else {
con.printf("Passwords do not match.%n");
}
Arrays.fill(pwd1, ' ');
Arrays.fill(pwd2, ' ');Console Methods Reference
Console provides a small focused API. It is not a general-purpose I/O class — it is specifically designed for interactive terminal sessions with a human user. For non-interactive input or IDE environments, fall back to Scanner or BufferedReader.
Java
Console console = System.console();
// ── Reading methods: ──────────────────────────────────────────────────
// readLine() — read a line, returns null at end of stream:
String line = console.readLine();
// readLine(fmt, args) — display formatted prompt then read:
String name = console.readLine("Hello %s, enter city: ", "Alice");
// readPassword() — read without echo, returns char[]:
char[] pwd = console.readPassword();
// readPassword(fmt, args) — formatted prompt, no echo:
char[] pwd2 = console.readPassword("Password for %s: ", username);
// ── Writing methods: ──────────────────────────────────────────────────
// printf(fmt, args) — formatted output, returns Console for chaining:
console.printf("Name: %s, Age: %d%n", "Alice", 30);
console.printf("Pi = %.5f%n", Math.PI);
// format(fmt, args) — identical to printf, returns Console:
console.format("Score: %d/%d%n", 85, 100);
// writer() — returns PrintWriter for advanced output:
PrintWriter writer = console.writer();
writer.println("Writing via PrintWriter");
writer.printf("Value: %d%n", 42);
// flush() — flush output buffer:
console.flush();
// ── Chaining console calls: ───────────────────────────────────────────
console.printf("=== Login ===%n")
.printf("System: %s%n", System.getProperty("os.name"));
String user = console.readLine("Username: ");
char[] pass = console.readPassword("Password: ");
// ── Fallback pattern — Console not available in IDEs: ────────────────
public static String readInput(String prompt) {
Console console = System.console();
if (console != null) {
return console.readLine(prompt);
} else {
// Fallback for IDE / non-terminal environments:
System.out.print(prompt);
return new Scanner(System.in).nextLine();
}
}Complete Login Example
A complete interactive terminal login demonstrates all Console features together — formatted prompts, secure password reading, validation, retry logic, and zeroing sensitive data after use.
Java
import java.io.Console;
import java.util.Arrays;
public class TerminalLogin {
private static final int MAX_ATTEMPTS = 3;
// Simulated user store — in reality, store hashed passwords:
private static final String VALID_USER = "admin";
private static final char[] VALID_PASS = "p@ssw0rd".toCharArray();
public static void main(String[] args) {
Console console = System.console();
if (console == null) {
System.err.println("Must run from a terminal.");
System.exit(1);
}
console.printf("=== Secure Login ===%n%n");
for (int attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
String username = console.readLine("Username: ");
char[] password = console.readPassword("Password: ");
try {
if (authenticate(username, password)) {
console.printf("%nLogin successful. Welcome, %s!%n",
username);
startSession(username, console);
return;
} else {
int remaining = MAX_ATTEMPTS - attempt;
if (remaining > 0) {
console.printf(
"Invalid credentials. %d attempt(s) remaining.%n%n",
remaining);
} else {
console.printf(
"Too many failed attempts. Account locked.%n");
}
}
} finally {
// Always zero the password array — even if exception thrown:
Arrays.fill(password, ' ');
}
}
}
private static boolean authenticate(String user, char[] pass) {
return VALID_USER.equals(user) && Arrays.equals(VALID_PASS, pass);
}
private static void startSession(String user, Console console) {
console.printf("%nEnter commands (type 'exit' to quit):%n");
String command;
while ((command = console.readLine("> ")) != null) {
if ("exit".equalsIgnoreCase(command.trim())) {
console.printf("Goodbye, %s!%n", user);
break;
}
console.printf("Executing: %s%n", command);
}
}
}Related Topics in Java Basics
Variables in Java
A variable is just a named box in memory that holds a value. Java is strict about what goes in each box — you tell it the type upfront. Once you get this, the rest of Java clicks into place.
Data Types in Java
Java needs to know exactly what kind of data it's dealing with before it can store or process it. Integers, decimals, characters, true/false — each has its own type. Knowing which to use (and why) makes your programs efficient and bug-free.
Primitive Data Types
Java has eight primitive data types — the most basic building blocks for storing data. Unlike objects, primitives are stored directly in memory, making them fast and efficient. Understanding each type, its size, range, and when to use it is fundamental to writing correct Java programs.
Non-Primitive Data Types
Non-primitive data types — also called reference types — are everything beyond Java's eight primitives. Strings, arrays, classes, interfaces, enums, and records all fall into this category. They're more powerful than primitives, but they work differently in memory, comparison, and nullability. Understanding the distinction is essential for writing correct Java.