JAVA / LOOPS AND ARRAYS
Command-line arguments and programs that take input
Read values passed after the class name from the String[] args array, convert them safely to numbers, and fall back to Scanner input when nothing is passed.
What you will learn
- Use args.length to count arguments; args[0] is the first argument, not the class name
- Convert argument text yourself with Integer.parseInt and handle NumberFormatException
- Check args.length before indexing to avoid ArrayIndexOutOfBoundsException
- Wrap System.in in a Scanner when values are typed or piped in rather than passed at launch
Understanding Command-line arguments and programs that take input
When you run java Sum 4 15 3, the launcher takes every token after the class name, wraps them in a String[], and passes that array to main. It is an ordinary array, identical in kind to one you would build with new String[3], so args.length and index access behave exactly as they do for arrays you create yourself; the only difference is who filled it in. The surprise for anyone arriving from C or C++ is that args[0] is "4" and not "Sum": the class name is what the JVM needed in order to locate your main method, and it is never handed on as an argument.
Every element is text, always. The launcher receives tokens that the shell already split on unquoted whitespace, so 4 reaches you as the one-character String "4", and args[0] + args[1] concatenates instead of adding. Converting text to a number is your job, and Integer.parseInt throws NumberFormatException on anything it cannot read, which is why argument handling starts with counting and validating rather than with arithmetic.
Arguments are fixed at the moment of launch, which suits values a script or scheduled job knows in advance; standard input is read while the program runs, which suits values a person types or another program pipes in. A Scanner built over System.in gives you nextInt and nextLine over that stream, and its hasNextInt style methods report end of input, which is normally what ends such a read loop. Because a run with no arguments yields a zero-length array and never null, the first thing a program that needs input should do is test args.length, and only then index.
public class Sum {
// run: java Sum 4 15 3
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("usage: java Sum <whole number> ...");
return;
}
int total = 0;
for (int i = 0; i < args.length; i++) {
total += Integer.parseInt(args[i]);
}
System.out.println("arguments: " + args.length);
System.out.println("total: " + total);
}
}Command-line arguments arrive as a plain String array whose length you must check before indexing and whose text you must convert yourself.
Worked examples
What is actually in the array
Prints the length and every element so you can see how the launcher and the shell divided your command line.
public class Args {
// run: java Args alpha "two words" 3
public static void main(String[] args) {
System.out.println("args.length = " + args.length);
for (int i = 0; i < args.length; i++) {
System.out.println(i + ": [" + args[i] + "] len=" + args[i].length());
}
}
}Example explained
Line 1args.length is 3, not 4: the class name Args was consumed by the launcher and never entered the array.
Line 2Index 0 holds alpha, which confirms that the first thing you typed after the class name is args[0].
Line 3args[1] is one element containing a space, len=9, because the quotes told the shell to keep it together.
Line 4args[2].length() is 1, showing that 3 arrived as a one-character String and not as an int.
Validate the count, then parse
Rejects the wrong number of arguments and turns a bad number into a message instead of a stack trace.
public class Repeat {
// run: java Repeat 3 ha
public static void main(String[] args) {
if (args.length != 2) {
System.out.println("need exactly 2 arguments, got " + args.length);
return;
}
int times;
try {
times = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.out.println("not a whole number: " + args[0]);
return;
}
for (int i = 0; i < times; i++) {
System.out.println((i + 1) + " " + args[1]);
}
}
}Example explained
Line 1The args.length != 2 test runs before any index is used, so java Repeat prints a count instead of crashing.
Line 2Integer.parseInt(args[0]) is the single point where text becomes a number, so it is the only place that needs the catch.
Line 3args[1] is printed as it stands because a word needs no conversion.
Line 4The loop bound comes from the parsed argument, so the caller decides how many lines appear.
Values from standard input instead
Reads numbers typed or piped into the program, with end of input ending the loop.
import java.util.Scanner;
public class Total {
// run: echo 1.5 2 3.25 | java Total
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
double total = 0;
int count = 0;
while (in.hasNextDouble()) {
total += in.nextDouble();
count++;
}
in.close();
System.out.println(count + " values, total " + total);
}
}Example explained
Line 1args is unused here: the values arrive on System.in, supplied by the pipe rather than by the command line.
Line 2hasNextDouble() returns false once the stream is exhausted, and that is what stops the while loop.
Line 3nextDouble() consumes one token per call, so the spaces between the three numbers do the splitting.
Line 4total prints as 6.75 because it is a double, not a rounded int.
Important notes
When the JVM starts your main, args is never null; with no arguments it is a zero-length array, so if (args == null) is dead code and args.length == 0 is the real test.
The shell, not Java, expands wildcards, so java Show *.txt can arrive as many separate arguments on Unix rather than the literal string *.txt.
Common mistakes
Assuming args[0] is the class or program name, a habit from C: the first real value gets skipped and every index is off by one, so the program quietly computes with the wrong data.
Indexing args[1] before checking args.length, so a run with no arguments dies with ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 0.
Doing arithmetic on the raw text: with 2 and 3 on the command line, args[0] + args[1] prints 23 because + on Strings concatenates, and args[0] == "2" compares references rather than characters.
Try it yourself
Change, predict, then run
Write a program that treats every argument as a Celsius temperature and prints the Fahrenheit value on its own line, printing a skip message for any argument that is not a number. Test it with java Convert 0 100 abc -40 and again with no arguments at all.
Open the Java workspaceCheck your understanding
A program's main begins with int n = Integer.parseInt(args[1]); and it is launched as java Count 7. What happens?
- It throws ArrayIndexOutOfBoundsException, because args has length 1 and index 1 does not exist
- n becomes 7, because args[0] holds the class name Count and args[1] holds 7
- It throws NumberFormatException, because 7 arrives as text rather than as a number
- n becomes 0, because array slots that were never filled default to 0
Show answer
Only what follows the class name is passed to main, so args is {"7"}: length 1, valid index 0 only, and args[1] is out of bounds. Option 2 is the C habit of expecting the program name at index 0, which Java deliberately omits. A NumberFormatException would need text that is not a valid int, and "7" parses cleanly.