Remember that Java programs are executed on the command line using the java command. The java command takes a fully-qualified class name as an argument; this class's main method is where program execution begins.
Let's look at a basic class that prints out a date and message:
package arunsoft.method;
import java.util.Date;
public class Message1 {
public static void main(String []args) {
Date now = new Date();
String message = now.toString();
message += ":";
message += "Hello";
System.out.println(message);
}
}
Compile and execute Message1.java from a DOS or UNIX shell:
Kevin-Taylors-Computer:~/src ktaylor$ javac methods/Message1.java Kevin-Taylors-Computer:~/src ktaylor$ java methods.Message1 Thu Jan 20 21:57:02 CST 2005:Hello
Behind the scenes, the JVM finds methods.Message1 in the classpath and begins executing main(). When main() exits, the program ends and the JVM shuts down.
Let us take a closer look at the attributes of main():
The version of main() above has the message hardcoded. This isn't very useful, so let's update main() so we can pass a message into main() as an argument on the java command line. Change Message1's main() to the following:
public static void main(String []args) {
// Make sure the command
// line argument was passed in
if(null == args || args.length < 1) {
// Command line argument
// doesn't exist, so exit with
// an error flag
System.exit(1);
}
// Timestamp the message
Date now = new Date();
String message = now.toString();
message += ": ";
// Extract the only command line
// argument from the first element
// of the array
message += args[0];
System.out.println(message);
}
The new version of Message1 can be executed with the following command line:
java example.Message1 "Hello from the command line"
Command line arguments are delimited by spaces, so arguments that contain spaces must be wrapped in double quotes, otherwise each word will be considered a separate argument. (Remember, this program only prints out the first element.)
Message1.main() does all the work in our program. It retrieves the command line arguments from the args parameter, prepends a timestamp to it, and then prints it out. This is a lot of work for one method. A good coding practice is to write small methods that do only one thing. This makes it more likely that you will be able to reuse that small bit of functionality. Also, if you need to change the functionality and it is contained in a single method, you only need to make the change in that one place.
In our example, what if we want to print out each element of the array on its own line, instead of just the first element? It will be much easier to make this change if we first break out the current functionality that creates a timestamp into its own method. Here is a new version, Message2, that does just that:
package methods;
import java.util.Date;
public class Message2 {
public static void main(String []args) {
// Make sure the command
// line argument was passed in
if(null == args || args.length < 1) {
// Command line argument
// doesn't exist, so exit with
// an error flag
System.exit(1);
}
// Extract the only command line
// argument from the first element
// of the array
String message = args[0];
String formattedMessage = prependTimestamp(message);
System.out.println(formattedMessage);
}
public static String prependTimestamp(String str) {
Date now = new Date();
String timeStamp = now.toString();
return timeStamp + ": " + str;
}
}
Message2 has the same behavior as Message1. But, now the code in prependTimestamp is reusable. Any code that needs to prepend the current date to a String can call this method. An added benefit is that the method name clearly indicates what the method does; this reduces the need for an explaining comment.
Note: Always strive to use clear, meaningful identifiers for classes, methods, and variables. This will reduce the number of comments needed in your code by clearly expressing the intent of the program. This is know as "programming by intention."
Now let's update Message2 so that it loops through the elements in the args array and prints out each element. Move the current code that reads and prints out the first array element into its own method named printMessages(String []messages). Then, update main() to call this new method. Finally, update printMessages to loop through the array.
Note: Make the change in the order I specified. When changing the internal structure of code (know as refactoring), it is critical to do it in small steps, compiling and testing after each step.
I have renamed the final class as Message3. Here it is:
package methods;
import java.util.Date;
public class Message3 {
public static void main(String []args) {
// Make sure the command
// line argument was passed in
if(null == args || args.length < 1) {
// Command line argument
// doesn't exist, so exit with
// an error flag
System.exit(1);
}
printMessages(args);
}
public static void printMessages(String []messages) {
if(null == messages) {
return;
}
for(int i = 0; i < messages.length; i++) {
String formattedMessage = prependTimestamp(messages[i]);
System.out.println(formattedMessage);
}
}
public static String prependTimestamp(String str) {
Date now = new Date();
String timeStamp = now.toString();
return timeStamp + ": " + str;
}
}