Strings
Strings can be created with the new operator, or set to a string literal at compile time, which is converted to a String object. In addition, many functions return a String object which can be assigned to a String variable, such as String.format.
    String s = new String("Hi there!");
    String t = "This works too.";
    String u = String.format("Line %d", 1);
Strings are:
  • Objects, not primitives.
  • Internally represented with 16-bit Unicode characters.
  • Immutable - once set, they can't be changed. They have the "appearance" of being changeable, but internally, all the routines that manipulate a string actually discard the reference to the old string object, and create a new string object. If no other references point to the old string object, it becomes eligible for garbage collection.

    This implies there are no 'in-place' string methods - all string methods that manipulate a string, return a string. Thus, if you perform an s.trim() without assigning the result to a String variable, it appears nothing has happened. What actually happened was a new String object was created that consisted of the original string with the whitespace trimmed, but since it didn't get assigned to a variable, it was immediately eligible for garbage collection.

        String s = " excess white space ";
        s.trim();     // NO! Doesn't modify s!
        s = s.trim(); // YES! This modifies s!
    
Use string1.equals(string2) to check whether or not two strings contain the exact same characters. Even though your code will compile fine if you use ==, you will get unexpected results.
== checks whether or not two string variables point to the same object, not whether or not the strings are meaningfully equivalent.
Common String Instance Methods
charAt(int index)Returns the character located at the specified index.
concat(String s)Returns the current string with the string s appended to the end.
equals(String s)Inherited from Object - Returns whether or not the characters in the current string, match the characters in string s.
equalsIgnoreCase()Same as equals, except case insensitive. Think of it as converting both strings to lowercase before comparing.
length()Returns the length of the current string. NOTE THAT IT'S A FUNCTION, NOT A VARIABLE! There are parentheses on the end of it.
replace(String X, String Y)Returns a string that contains all the old string X's replaced with the new string Y's.. Example:
        String cat = "The cat";
        cat = cat.replace("The", "The furry");
        System.out.println(cat);
prints "The furry cat."
replace(char X, char Y)Returns a string that contains all the old char X's replaced with the new char Y's.
substring(int begin)Returns a part of the current string, starting at character begin, and ending at the end of the current string.
substring(int begin, int end)Return a part of the current string, starting at character begin, and ending at character end-1. It's 'exclusive' of the end, so this:
    new String("The furry cat").substring(4, 9);
returns "furry", which are characters 4, 5, 6, 7, and 8 of the string.
toLowerCase()Returns the current string with all characters lower case.
toUpperCase()Returns the current string with all characters upper case.
toString()Returns the string value of the current string.
trim()Returns the current string with leading and trailing white space removed. Java considers white space to be one of the following:
Decimal   Octal   Hex    Binary    Unicode  Value
-------   -----   ---    ------    -------  -------------------------
  009      011    009   00001001   '\u0009'   HT    Horizontal Tab
  010      012    00A   00001010   '\u000A'   LF    Line Feed
  011      013    00B   00001011   '\u000B'   VT    Vertical Tab
  012      014    00C   00001100   '\u000C'   FF    Form Feed
  013      015    00D   00001101   '\u000D'   CR    Carriage Return
  028      034    01C   00011100   '\u001C'   FS    File Separator
  029      035    01D   00011101   '\u001D'   GS    Group Separator
  030      036    01E   00011110   '\u001E'   RS    Record Separator
  031      037    01F   00011111   '\u001F'   US    Unit Separator
  032      040    020   00100000   '\u0020'   SP    Space
  160      240    0A0   10100000   '\u00A0'   NBSP  Non breaking space
String Pool
To optimize performance, Java stores all string literals in the program, in a "string pool" managed by the String class. Thus, if 5 different variables all point to the same string literal, they all share the same object. This doesn't result in contention though, because the immutability of strings ensures that as soon as a string variable is modified, it points to a new string - thus it's not possible to modify the string 'out from under' the other 4 variables.
The programmer can take advantage of the string pool themselves, by using the "intern" method. To place a String in the string pool, call the instance method "intern" on the string. Example:
	s = s.intern();
where "s" is the string you wish to place in the pool. Interned strings compare faster than normal strings. I have a complex example where this proved true, but can't come up with a simple example that proves my point. My complex example showed interned string comparisons ran about 25% faster than normal string comparisons.

Unproven Theory: I THINK that if both strings being compared exist in the string pool, the JVM knows enough to make it a simple == check (seeing if the objects point to the same string), rather than the longer .equals check, which checks character by character. But this is only my personal theory.

StringBuilder and StringBuffer
StringBuffer is thread safe, because its methods are synchronized.
StringBuilder was added in Java 5. It has exactly the same methods as StringBuffer, but its methods are not synchronized, and it's not thread safe. However, it IS faster, and Sun recommends that you use StringBuilder instead of StringBuffer whenever possible.
StringBuilder and StringBuffer can't be created with string literals, like String can - you must create a new StringBuffer or StringBuilder object instead, and pass in the starting value, if desired. Syntax:
    StringBuilder sb = new StringBuilder("My special string");
All the StringBuffer and StringBuilder methods that manipulate strings, operate directly on the value of the instance object calling the method. Thus, you can think of these methods as running 'in place' on the string. Contrast this to the String operations up above, which require assigning the result to a String variable.
The return value of the most common StringBuilder methods is the current StringBuilder itself, so you can concatenate operations, like:
    dog.replace(10, 13, "dog").reverse().toString();
StringBuilder and StringBuffer .equals does not compare character sequences, it is the equivalent of a == - it only checks for object equality. Don't expect two exactly-the-same StringBuilders to compare equal, because they won't.
Common String Buffer and String Builder Methods
StringBuilder append(XXX argument)Appends the string value of the specified argument to the end of the string buffer. XXX can be: CharSequence, Object, String, StringBuffer, boolean, char, char[], double, float, int, long.
StringBuilder delete(int start, int end)Removes the characters in a substring of the current string buffer. The substring begins at the specified start and extends to the character at index end - 1 or to the end of the string buffer if no such character exists. If start is equal to end, no changes are made.
StringBuilder deleteCharAt(int index)Removes the char at the specified position in the current string buffer. This sequence is shortened by one char.
StringBuilder insert(int offset, XXX s)Inserts the string of the argument into the string buffer. The second argument is converted to a string as if by the method String.valueOf, and the characters of that string are then inserted into this sequence at the indicated offset. The offset argument must be >=0, and <= the length of the current string buffer.
XXX can be: CharSequence, Object, String, StringBuffer, boolean, char, char[], double, float, int, long.
StringBuilder replace(int start, int end, String str)Replaces the characters in a substring of this string buffer with characters in the specified string. Example:
  StringBuilder cat = new StringBuilder("The cat");
  cat.replace(4, 4, "furry "); 
  // cat is now "The furry cat"		
prints "The furry cat."

NOTE THE SYNTAX IS DIFFERENT THAN STRING! In the String object, you specify the 'find' phrase and the 'replace' phrase. In the StringBuffer object, you specify the beginning and ending characters instead of the 'find' phrase. The end character is exclusive. If the start and end character are the same, this method performs an insert. If the end character is higher than the start character, this method removes the characters specified by the start and end arguments, and inserts the specified string at that point.

StringBuilder reverse()Reverse the characters of the current string buffer.
String substring(int begin)Returns a part of the current StringBuilder as a String, starting at character begin, and ending at the end of the current StringBuilder.
String substring(int begin, int end)Return a part of the current StringBuilder as a String, starting at character begin, and ending at character end-1. It's 'exclusive' of the end, so this:
new StringBuilder("The furry cat").substring(4, 9);
returns "furry", which are characters 4, 5, 6, 7, and 8 of the StringBuilder.
String toString()Return the value of the current string buffer as a String.
Here is an example using several methods of StringBuilder:
        // Won't compile - must create the StringBuilder object.
        // StringBuilder cat = "The cat";
		
        StringBuilder cat = new StringBuilder("The cat");
        cat.replace(4, 4, "furry ");
		// cat is now "The furry cat"
        System.out.println(cat);
        // Prints     "The furry cat		
        StringBuilder dog = new StringBuilder("The furry cat"); 
        // dog is now "The furry cat."
		
        // .equals doesn't compare character sequences in StringBuilder
        if (cat.equals(dog))
            System.out.println("cat == dog");
        else
            System.out.println("cat <> dog");                  
        // Prints      "cat <> dog"

        // The return value of many StringBuilder methods is the current object itself,
        // so you can concatenate operations, like:
        // dog.replace(10, 13, "dog").reverse().toString();
        // Therefore, the following lines both modify AND print the StringBuilder object.
        System.out.println(dog.replace(10, 13, "dog"));         
        // Prints     "The furry dog"
        System.out.println(dog.replace(4, 9, "barking"));       
        // Prints     "The barking dog"

File IO
CHECK THE IMPORTS! Most of these objects in file IO require the package java.io.* be imported first!
File
The File object is an abstract representation of file and directory pathnames. You don't use the File class to actually read or write files, it's used to make and delete files and directories, perform searches, and manipulate pathnames.
constructor File(String pathname) Creates a new File instance by converting the given pathname string into an abstract pathname.
constructor File(String parent, String child) Creates a new File instance from a parent pathname string and a child pathname string.
constructor File(File parent, String child) Creates a new File instance from a parent abstract pathname and a child pathname string.
boolean createNewFile() If a file with this name does not yet exist, creates a new, empty file named by this abstract pathname. Returns true if a file with name didn't exist and was created.
boolean delete()Deletes the file or directory specified by this abstract pathname. If this File object is a directory, then the directory must be empty in order to be deleted. Return true if the file or directory is successfully deleted.
boolean exists()Returns whether the file or directory specified by this abstract pathname exists.
boolean isDirectory()Returns whether the file specified by this abstract pathname exists, and is a directory.
boolean isFile()Returns whether the file specified by this abstract pathname exists, and is a normal file, ie, not a directory.
String[] list()Returns an array of strings naming the short names (no path information) of files and directories in the directory denoted by this abstract pathname. If the abstract pathname is not a directory, it returns null.
File[] listFiles() Returns an array of abstract pathnames denoting the files in the directory denoted by this abstract pathname. If this abstract pathname does not denote a directory, then this method returns null.
boolean mkdir()Creates the directory named by this abstract pathname. Returns true if the directory was created.
boolean mkdirs() Creates the directory named by this abstract pathname, including any necessary but nonexistent parent directories. Note that if this operation fails it may have succeeded in creating some of the necessary parent directories. Returns true if the directory plus all necessary parent directories were created.
boolean renameTo()Renames the file or directory denoted by this abstract pathname, and returns the success or failure of the operation. Note that it's OK to rename a directory, even if it's not empty.
FileReader
The FileReader object is used to read character files. Its read methods are low-level, and allow you to read single characters, fixed number of characters, or all characters. FileReaders are usually wrapped by higher level objects such as BufferedReader.
constructor FileReader(File file) throws FileNotFoundException Creates a new FileReader, given the File to read from.
constructor FileReader(String fileName) throws FileNotFoundException Creates a new FileReader, given the name of the file to read from.
int read() throws IOExceptionRead a single character. Returns the int value of the character read, or -1 if EOF is reached.
int read(char[] cbuf, int offset, int length) throws IOExceptionRead characters into a portion of an array, where
    cbuf   = Destination buffer
    offset = Offset at which to start storing characters
    length = Maximum number of characters to read
Returns the number of characters read, or -1 if the end of the stream has been reached.
BufferedReader
The BufferedReader object is used to read character files. Its read methods are higher level, and in addition to the functions available in FileReader, it allows you to read characters a line at a time. It uses a buffer to enhance performance.
constructor BufferedReader(Reader in) Create a buffering character-input stream using the given reader.
int read() throws IOExceptionRead a single character. Returns the int value of the character read, or -1 if EOF is reached.
int read(char[] cbuf, int offset, int length) throws IOExceptionRead characters into a portion of an array, where
    cbuf   = Destination buffer
    offset = Offset at which to start storing characters
    length = Maximum number of characters to read
Returns the number of characters read, or -1 if the end of the stream has been reached.
String readLine() throws IOExceptionRead a line of text. A line is considered to be terminated by either a line feed ('\n'), a carriage return ('\r'), or a crlf ('\r\n').
FileWriter
The FileWriter object is used to write to character files. Its write methods are low-level - this class is usually wrapped by a higher level object such as BufferedWriter.
constructor FileWriter(File file) throws IOExceptionConstructs a FileWriter object given a File object.
constructor FileWriter(File file, boolean append) throws IOExceptionConstructs a FileWriter object given a File object with a boolean indicating whether or not to append the data written..
constructor FileWriter(String fileName) throws IOExceptionConstructs a FileWriter object given a file name.
constructor FileWriter(String fileName, boolean append) throws IOException Constructs a FileWriter object given a file name with a boolean indicating whether or not to append the data written.
close() throws IOExceptionClose the stream.
flush() throws IOExceptionFlush the stream.
write(int c) throws IOExceptionWrite a single character.
write(char[] cbuf, int off, int len) throws IOExceptionWrite a portion of an array of characters, where
    cbuf = A character array
    off  = Offset from which to start reading characters
    len  = Number of characters to write 
write(String str, int off, int len) throws IOExceptionWrite a portion of a string, where
    str  = A string
    off  = Offset from which to start reading characters
    len  = Number of characters to write 
BufferedWriter
The BufferedWriter object is used to write to character files. Its write methods are higher-level, and in addition to the functions available in FileWriter, it provides a newLine() method to create platform-specific line separators automatically.
close() throws IOExceptionClose the stream.
flush() throws IOExceptionFlush the stream.
newLine() throws IOExceptionWrite a line separator.
write(int c) throws IOExceptionWrite a single character.
write(char[] cbuf, int off, int len) throws IOExceptionWrite a portion of an array of characters, where
    cbuf = A character array
    off  = Offset from which to start reading characters
    len  = Number of characters to write 
write(String str, int off, int len) throws IOExceptionWrite a portion of a string, where
    str  = A string
    off  = Offset from which to start reading characters
    len  = Number of characters to write 
PrintWriter
The PrintWriter object is used to write to character streams. Its write methods are higher-level, and allow you to access printf-style functionality on the output stream.
constructor PrintWriter(File file) throws FileNotFoundExceptionCreates a new PrintWriter, without automatic line flushing, with the specified file.
constructor PrintWriter(String filename) throws FileNotFoundExceptionCreates a new PrintWriter, without automatic line flushing, with the specified file name.
constructor PrintWriter(OutputStream out)Create a new PrintWriter, without automatic line flushing, from an existing OutputStream.
constructor PrintWriter(Writer out) throws FileNotFoundExceptionCreate a new PrintWriter, without automatic line flushing.
close()Close the stream.
flush()Flush the stream.
format(String format, Object... args)Writes a formatted string to this writer using the specified format string and arguments.
printf(String format, Object... args)A convenience method to write a formatted string to this writer using the specified format string and arguments.
print(XXX arg)Prints the argument.
println(XXX arg)Prints the argument and then terminates the line.
write(XXX arg)Writes the argument.
Console
The Console object is used to write to read and write text from the system console. Note that the system console may not exist on all systems - check for the console being null, after obtaining it, but before using it. To obtain a console, use the following syntax:
        Console console = System.console();
        if (console == null)
            throw new RuntimeException("Couldn't get console!");
Console format(String fmt, Object... args)Writes a formatted string to this console's output stream using the specified format string and arguments.
String readLine() Reads a single line of text from the console. Returns a string containing the line read from the console, not including any line-termination characters, or null if an end of stream has been reached.
String readLine(String fmt, Object... args) Provides a formatted prompt, then reads a single line of text from the console. Returns a string containing the line read from the console, not including any line-termination characters, or null if an end of stream has been reached.
char[] readPassword() Reads a password or passphrase from the console with echoing disabled. Returns a character array containing the password or passphrase read from the console, not including any line-termination characters, or null if an end of stream has been reached.
char[] readPassword(String fmt, Object... args) Provides a formatted prompt, then reads a password or passphrase from the console with echoing disabled. Returns a character array containing the password or passphrase read from the console, not including any line-termination characters, or null if an end of stream has been reached.
IO Examples
Following is an example illustrating some of these concepts:
import java.io.*;
import java.util.*;

public class testIO {

    public static void main(String[] args) {
        String filename = "xxx";
        StringBuilder sb = new StringBuilder();
        sb.append("These are some lines\nfor the new\nfile.\n");

        if (FileExists(filename))               // if file exists,
            FileRemove(filename);               //   remove it.
        FileCreate(filename);                   // Create a new file.
        FileWrite(filename, sb.toString());     // Write some text to the file.

        // Make sure the normal file read is OK
        String s = FileRead(filename);          // Read some text from the file.
        if (!s.equals(sb.toString()))
            throw new RuntimeException("The FileRead failed!");

        // Make sure the buffered file read is OK
        // Read some buffered text from the file.
        String[] lines = BufferedFileRead(filename);  
        String[] orig = s.split("\n");
        if (lines.length != orig.length)
            throw new RuntimeException("The BufferedFileRead failed!");
        for (int i = 0; i < lines.length; i++) {
            if (!lines[i].equals(orig[i]))
                throw new RuntimeException("The BufferedFileRead failed!");
            else
                System.out.println(lines[i]);
        }

        // Overwrite an existing file
        FileWrite(filename, "This is some new text!");
        for (String line : BufferedFileRead(filename))
            System.out.println(line);

        // Console test
        ConsoleTest();
    }

    public static boolean FileExists(String filename) {
        // Return whether or not a file exists.
        File file = new File(filename);
        return file.exists();
    }

    public static boolean FileRemove(String filename) {
        // Delete a file, returning false if it doesn't exist.
        File file = new File(filename);
        if (!file.exists())
            return false;
        file.delete();
        return true;
    }

    public static boolean FileCreate(String filename) {
        // Create a text file, returning false if it already exists.
        File file = new File(filename);
        if (file.exists())
            return false;
       try {
           file.createNewFile();                    // Could throw IOException
       } catch (IOException ex) {
           throw new RuntimeException(ex);
       }
       return true;
    }

    public static boolean FileWrite(String filename, String s) {
        // Write a line of text to a file.
        File file = new File(filename);

        if (!file.exists())
            return false;

        try {
            FileWriter fd = new FileWriter(file);   // Could throw IOException
            fd.write(s);
            fd.close();
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }

        return true;
    }

    public static String FileRead(String filename) {
        // Read a file as text, returning the entire contents as a string.
        File file = new File(filename);
        try {
            FileReader fd = new FileReader(file);   // Could throw FileNotFoundException
            int ch;
            StringBuilder sb = new StringBuilder();
            do {
                ch = fd.read();                     // Could throw IOException
                if (ch != -1) {
                    // You must cast the value to a char!
                    // Strangely enough, ch is an int, not a char.
                    // However, there is no FileReader.read method
                    // that returns a char - only an int.
                    sb.append((char)ch); 
                }
            } while (ch != -1);
            fd.close();                             // Could throw IOException
            return sb.toString();
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    public static String[] BufferedFileRead(String filename) {
        // Read a file as text, returning an array of lines.
        File file = new File(filename);
        List<String> lst = new ArrayList<String>();
        String s;
        try {
            FileReader fd = new FileReader(file);   // Could throw FileNotFoundException
            BufferedReader br = new BufferedReader(fd);
            while ((s = br.readLine()) != null)     // Could throw IOException
                lst.add(s);
            fd.close();                             // Could throw IOException
            String[] arr = new String[lst.size()];
            for (int i = 0; i < lst.size(); i++)
                arr[i] = lst.get(i);
            return arr;
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    public static void ConsoleTest() {
        Console console = System.console();
        if (console == null)
            throw new RuntimeException("Couldn't get console!");
        console.format("Line: %d", 2);
        String s = console.readLine("%s", "Enter your logonid:");
        char[] password = console.readPassword("Password:");
    }
}

Serialization
Serialization allows you to save objects to files or output streams quickly and easily. It saves the object, and all its instance variables. To make a class serializable, simply implement interface Serializable. This is a marker interface, one that requires no routines to be implemented. A couple of caveats:
  • If you mark a class serializable, you must import java.io.*
  • For a class to be serializable, all its instance variables must be serializable.
  • Only instance variables are serialized - static variables are not.
  • Versioning problems can happen. If you save a MyCat object using one version of the class, but deserialize it using a different version of the class, deserialization might fail.
  • To prevent instance variables from being serialized, mark them as 'transient' so the serialization process won't attempt to store them.
  • For variables that can't be serialized, mark them as 'transient', or override the readObject and writeObject routines in the main class to handle them separately.
  • The signature for the two methods are:
        
    	private void readObject(ObjectInputStream is)
    	private void writeObject(ObjectOutputStream os)
    
    Note they are PRIVATE, return void, and have a single argument.
  • If you override readObject and writeObject, remember that the order you write the custom data in writeObject, is the order you must read them in, in readObject.
  • When overriding writeObject and readObject, note that there IS no 'writeString' or 'readString' method - you must use something else instead, such as 'writeUTF' and 'readUTF'.
When an object is deserialized, the constructor IS NOT RUN. When an object is created using new, the following happens:
  • All instance variables are assigned default values.
  • The constructor is invoked, which immediately invokes the superclass constructor, etc.
  • All superclass constructors complete.
  • Instance variables that are initialized as part of their declaration are assigned their initial value (as opposed to the default value they have prior to the superclass constructors completing.)
  • The constructor completes.
However, when it is deserialized, ALL THOSE STEPS DON'T HAPPEN! Initial values never pop up, only default values. This implies object references marked 'transient' will always reconstitute to null, regardless of whether the class initializes them in the declaration, or not.

In addition, if a serializable subclass inherits from a non-serializable superclass, the constructors at superclass level and above will run. For all variables the subclass inherits from the superclass, the superclass will 'eat' the deserialized value of the subclass, and revert it to its default value as initialized in the superclass.

Here's an example showing a custom serialization process for a class, that has an instance variable that is not serializable.

import java.io.*;

public class testSerializable {
    public static void main(String... args) {
        Person p = new Person("Kevin", 45, 65, 198);
        p.cat = new MyCat("Fluffy", "orange");
        String filename = String.format("%s.ser", p.name);
        p.SaveToFile(filename);
        Person q = Person.LoadFromFile(filename);
        System.out.printf("p = %s\n", p);
        System.out.printf("q = %s\n", q);
    }
}

class Person extends SerializeMe {
    public String name;
    protected int age;
    int height;
    private int weight;
    public transient MyCat cat;
    public Person() {
        System.out.printf("no-arg Person constructor\n");
    }
    public Person(String name, int age, int height, int weight) {
        System.out.printf("Person constructor: %s %d %d %d\n", 
            name, age, height, weight);
        this.name   = name;
        this.age    = age;
        this.height = height;
        this.weight = weight;
    }
    public int getWeight() {
        System.out.printf("getWeight %d\n", weight);
        return weight;
    }
    public void setWeight(int weight) {
        System.out.printf("setWeight %d\n", weight);
        this.weight = weight;
    }
    @Override
    public String toString() {
        return String.format("Name: %s Age: %d Height: %d Weight: %d Cat name: %s " + 
          "Cat color: %s", name, age, height, weight, cat.getName(), cat.getColor());
    }
    private void writeObject(ObjectOutputStream os) {
        try {
            os.defaultWriteObject();
            os.writeUTF(cat.getName());
            os.writeUTF(cat.getColor());
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    }
    private void readObject(ObjectInputStream is) {
        try {
            is.defaultReadObject();
            this.cat = new MyCat("", "");
            cat.setName(is.readUTF());
            cat.setColor(is.readUTF());
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}

class SerializeMe implements Serializable {
    public void SaveToFile(String filename) {
        // Write the object to the specified filename.
        try {
            FileOutputStream fs = new FileOutputStream(filename);
            ObjectOutputStream os = new ObjectOutputStream(fs);
            os.writeObject(this);
            os.close();
            System.out.printf("Saved %s to file %s\n", this.toString(), filename);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
    public static <T> T LoadFromFile(String filename) {
        // Read the object from the specified filename.
        try {
            FileInputStream fis = new FileInputStream(filename);
            ObjectInputStream ois = new ObjectInputStream(fis);
            // The following does NOT call the constructor!
            T o = (T)ois.readObject();
            ois.close();
            System.out.printf("Loaded %s from file %s\n", o.toString(), filename);
            return o;
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}

class MyCat {
    private String name;
    private String color;
    public MyCat(String name, String color) {
        this.name = name;
        this.color = color;
    }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getColor() { return color; }
    public void setColor(String color) { this.color = color; }
}
The output of the above program is:
Person constructor: Kevin 45 65 198
Saved Name: Kevin Age: 45 Height: 65 Weight: 198 Cat name: Fluffy Cat 
   color: orange to file Kevin.ser
Loaded Name: Kevin Age: 45 Height: 65 Weight: 198 Cat name: Fluffy Cat 
   color: orange from file Kevin.ser
p = Name: Kevin Age: 45 Height: 65 Weight: 198 Cat name: Fluffy Cat 
   color: orange
q = Name: Kevin Age: 45 Height: 65 Weight: 198 Cat name: Fluffy Cat 
   color: orange

Date, Time, Locale, and NumberFormat
Date Class
  • To use the Date class, you'll have to import java.util.Date.
  • The Date class is mostly deprecated; it's unaffected by time zones, and in most cases, you'll want to use the Calendar class instead.
  • An instance of the Date class represents a single date and time. Internally, the Date class is a primitive long that holds the number of milliseconds (NOT seconds!) between the date it represents and January 1, 1970. If this number goes negative, it represents a date BEFORE January 1, 1970.
    Example:
            Date d1 = new Date();
            System.out.println(d1.getTime());
            d1.setTime(0);
            System.out.println(d1.toString());
            // Prints:
            // 1265601358033
            // Wed Dec 31 16:00:00 PST 1969
    
constructor Date()Allocates a Date object and initializes it so that it represents the time at which it was allocated, measured to the nearest millisecond.
constructor Date(long milliseconds)Allocates a Date object and initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
long getTime()Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object.
setTime(long time)Sets this Date object to represent a point in time that is the number of milliseconds after January 1, 1970 00:00:00 GMT.
Calendar Class
  • To use the Calendar class, you'll have to import java.util.Calendar.
  • You can't say "Calendar c = new Calendar" - you have to use a static factory method instead called "getInstance". Example:
    	Calendar c = Calendar.getInstance();
    
  • Calendar.getTime() returns a Date object, so
  • Calendar.getTime().getTime() returns the milliseconds since 1970.
static Calendar getInstance() Gets a calendar using the default time zone and locale. The Calendar returned is based on the current time in the default time zone with the default locale.
static Calendar getInstance(TimeZone zone) Gets a calendar using the specified time zone and default locale. The Calendar returned is based on the current time in the given time zone with the default locale.
static Calendar getInstance(Locale aLocale) Gets a calendar using the default time zone and specified locale. The Calendar returned is based on the current time in the default time zone with the given locale.
static Calendar getInstance(TimeZone zone, Locale aLocale) Gets a calendar with the specified time zone and locale. The Calendar returned is based on the current time in the given time zone with the given locale.
add(int field, int amount)Adds or subtracts the specified amount of time to the given calendar field, based on the calendar's rules. For example, to subtract 5 days from the current time of the calendar, you can achieve it by calling: add(Calendar.DAY_OF_MONTH, -5).
Available fields include:
    Calendar.YEAR
    Calendar.MONTH
    Calendar.DAY_OF_MONTH
    Calendar.HOUR
    Calendar.MINUTE
    Calendar.SECOND
roll(int field, int amount)Adds the specified (signed) amount to the specified calendar field without changing larger fields. A negative amount means to roll down.
Available fields include:
    Calendar.YEAR
    Calendar.MONTH
    Calendar.DAY_OF_MONTH
    Calendar.HOUR
    Calendar.MINUTE
    Calendar.SECOND
getTime()Returns a Date object representing this Calendar's time value (millisecond offset from the Epoch").
setTime(Date date)Sets this Calendar's time with the given Date.
setTimeInMillis(long millis)Sets this Calendar's current time from the given long value.
DateFormat Class
  • To use the DateFormat class, you'll have to import java.text.DateFormat.
  • You can't say "DateFormat df = new DateFormat()" - you have to use a static factory method instead called "getInstance". Example:
    	DateFormat df = DateFormat.getInstance();
    
static DateFormat getInstance() Get a default date/time formatter that uses the SHORT style for both the date and the time.
static DateFormat getDateInstance() Gets the date formatter with the default formatting style for the default locale.
static DateFormat getDateInstance(int style) Gets the date formatter with the given formatting style for the default locale.
Available styles include:
    DateFormat.SHORT     9/8/01
    DateFormat.MEDIUM    Sep 8, 2001
    DateFormat.LONG      September 8, 2001
    DateFormat.FULL      Saturday, September 8, 2001
static DateFormat getDateInstance(int style, Locale aLocale) Gets the date formatter with the given formatting style for the given locale.
Available styles include:
    DateFormat.SHORT     9/8/01
    DateFormat.MEDIUM    Sep 8, 2001
    DateFormat.LONG      September 8, 2001
    DateFormat.FULL      Saturday, September 8, 2001
String format(Date date) Formats a Date into a date/time string.
Date parse(String source) throws ParseException Parses text from the beginning of the given string to produce a date. The method may not use the entire text of the given string.
NumberFormat Class
The NumberFormat class can use an instance of Locale to customize formatted output to be specific to a locale.
  • Use this class to format numbers or currency values.
  • To use the NumberFormat class, you'll have to import java.text.NumberFormat.
  • You can't say "NumberFormat nf = new NumberFormat()" - you have to use a static factory method instead called "getInstance". Example:
    	NumberFormat nf = NumberFormat.getInstance();
    
static NumberFormat getInstance() Returns a general-purpose number format for the current default locale. This is the same as calling getNumberInstance().
static NumberFormat getInstance(Locale inLocale) Returns a general-purpose number format for the specified locale. This is the same as calling getNumberInstance(inLocale).
static NumberFormat getCurrencyInstance() Returns a currency format for the current default locale.
static NumberFormat getCurrencyInstance(Locale inLocale) Returns a currency format for the specified locale.
static NumberFormat getNumberInstance() Returns a general-purpose number format for the current default locale.
static NumberFormat getNumberInstance(Locale inLocale) Returns a general-purpose number format for the specified locale.
Locale Class
Both the DateFormat and the NumberFormat class can use an instance of Locale to customize formatted output to be specific to a locale.
A locale is a specific geographical, political, or cultural region.
constructor Locale(String language)Creates a new Locale object with the specified language, which must be a valid ISO Language Code.
constructor Locale(String language, String country)Creates a new Locale object with the specified language and country, which must be a valid ISO Language Code, and a valid ISO Country Code.
String getDisplayCountry() Returns a name for the locale's country that is appropriate for display to the user. If possible, the name returned will be localized for the default locale.
String getDisplayCountry(Locale inLocale) Returns a name for the locale's country that is appropriate for display to the user. If possible, the name returned will be localized according to inLocale. For example, if the locale is fr_FR and inLocale is en_US, getDisplayCountry() will return "France"; if the locale is en_US and inLocale is fr_FR, getDisplayCountry() will return "Etats-Unis". If the name returned cannot be localized according to inLocale. (say, we don't have a Japanese name for Croatia), this function falls back on the English name, and finally on the ISO code as a last-resort value. If the locale doesn't specify a country, this function returns the empty string.
String getDisplayLanguage() Returns a name for the locale's language that is appropriate for display to the user. If possible, the name returned will be localized for the default locale.
String getDisplayLanguage(Locale inLocale) Returns a name for the locale's language that is appropriate for display to the user. If possible, the name returned will be localized according to inLocale. For example, if the locale is fr_FR and inLocale is en_US, getDisplayLanguage() will return "French"; if the locale is en_US and inLocale is fr_FR, getDisplayLanguage() will return "anglais". If the name returned cannot be localized according to inLocale, (say, we don't have a Japanese name for Croatian), this function falls back on the English name, and finally on the ISO code as a last-resort value. If the locale doesn't specify a language, this function returns the empty string.
Examples
Following are some examples that illustrate the above concepts:

import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;


public class testDateTime {
    public static void main(String[] args) {
        testDate();
        testCalendar();
        testDateFormat();
        testLocale();
        testNumberFormat();
    }
    public static void testDate() {
        Date d1 = new Date();
        System.out.println(d1.getTime());           // 1265601358033
        d1.setTime(0);
        System.out.println(d1.toString());          // Wed Dec 31 16:00:00 PST 1969
    }
    public static void testCalendar() {
        Calendar c = Calendar.getInstance();        // defaults to now
        System.out.println(c.getTime());            // Sun Feb 07 20:14:41 PST 2010
        System.out.println(c.getTime().getTime());  // 1265602481314
        c.setTime(new Date());
        c.setTimeInMillis(0);
        System.out.println(c.getTime());            // Wed Dec 31 16:00:00 PST 1969
        System.out.println(c.toString());           // BIG LONG STRING - don't want.

        // Add a month to the date.
        c.add(Calendar.MONTH, 1);
        System.out.println(c.getTime());            // Sat Jan 31 16:00:00 PST 1970

        // Add 1 hour and 1 minute to the date.
        c.add(Calendar.HOUR, 1);
        c.add(Calendar.MINUTE, 1);
        System.out.println(c.getTime());            // Sat Jan 31 17:01:00 PST 1970

        // Subtract 3 seconds from the date.
        c.add(Calendar.SECOND, -3);
        System.out.println(c.getTime());            // Sat Jan 31 17:00:57 PST 1970

        // Add 1000 days to the date using roll.
        // This will affect the day of month only, and no other field.
        // Think of it as a 'modulo' for dates.
        c.roll(Calendar.DAY_OF_MONTH, 1000);
        System.out.println(c.getTime());            // Thu Jan 08 17:00:57 PST 1970
    }
    public static void testDateFormat() {
        Date d1 = new Date(1000000000000L);
        DateFormat[] formats = new DateFormat[6];
        formats[0] = DateFormat.getInstance();
        formats[1] = DateFormat.getDateInstance();
        formats[2] = DateFormat.getDateInstance(DateFormat.SHORT);
        formats[3] = DateFormat.getDateInstance(DateFormat.MEDIUM);
        formats[4] = DateFormat.getDateInstance(DateFormat.LONG);
        formats[5] = DateFormat.getDateInstance(DateFormat.FULL);

        for (DateFormat df : formats) {
            String s = df.format(d1);
            System.out.println(s);
        }
        
        // Prints
        // 9/8/01 6:46 PM
        // Sep 8, 2001
        // 9/8/01
        // Sep 8, 2001
        // September 8, 2001
        // Saturday, September 8, 2001

        for (DateFormat df : formats) {
            String s = df.format(d1);
            Date parseDate;
            try {
                parseDate = df.parse(s);   // could throw java.text.ParseException
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
            System.out.printf("%s  = %s\n", parseDate, d1);
        }

        // Prints
        // Sat Sep 08 18:46:00 PDT 2001  = Sat Sep 08 18:46:40 PDT 2001
        // Sat Sep 08 00:00:00 PDT 2001  = Sat Sep 08 18:46:40 PDT 2001
        // Sat Sep 08 00:00:00 PDT 2001  = Sat Sep 08 18:46:40 PDT 2001
        // Sat Sep 08 00:00:00 PDT 2001  = Sat Sep 08 18:46:40 PDT 2001
        // Sat Sep 08 00:00:00 PDT 2001  = Sat Sep 08 18:46:40 PDT 2001
        // Sat Sep 08 00:00:00 PDT 2001  = Sat Sep 08 18:46:40 PDT 2001
    }

    public static void testLocale() {
        Locale locUS =Locale.US;
        Locale locPT = new Locale("it");
        Locale locBR = new Locale("it", "CH");
        Calendar c = Calendar.getInstance();
        c.set(2010, 02, 07);
        Date d1 = c.getTime();
        
        DateFormat dfUS  = DateFormat.getInstance();
        DateFormat dfIT1 = DateFormat.getDateInstance(DateFormat.FULL, locPT);
        DateFormat dfIT2 = DateFormat.getDateInstance(DateFormat.FULL, locBR);

        System.out.println("US           " + dfUS.format(d1));
        System.out.println("Italy        " + dfIT1.format(d1));
        System.out.println("Switzerland  " + dfIT2.format(d1));
        // Output:
        // US           3/7/10 9:25 PM
        // Italy        domenica 7 marzo 2010
        // Switzerland  domenica, 7. marzo 2010

        System.out.println(locUS.getDisplayCountry(locUS) + " " + 
            locUS.getDisplayLanguage(locUS));
        System.out.println(locUS.getDisplayCountry(locPT) + " " + 
            locUS.getDisplayLanguage(locPT));
        System.out.println(locUS.getDisplayCountry(locBR) + " " + 
            locUS.getDisplayLanguage(locBR));
        System.out.println("");

        System.out.println(locPT.getDisplayCountry(locUS) + " " + 
            locPT.getDisplayLanguage(locUS));
        System.out.println(locPT.getDisplayCountry(locPT) + " " + 
            locPT.getDisplayLanguage(locPT));
        System.out.println(locPT.getDisplayCountry(locBR) + " " + 
            locPT.getDisplayLanguage(locBR));
        System.out.println("");

        System.out.println(locBR.getDisplayCountry(locUS) + " " + 
            locBR.getDisplayLanguage(locUS));
        System.out.println(locBR.getDisplayCountry(locPT) + " " + 
            locBR.getDisplayLanguage(locPT));
        System.out.println(locBR.getDisplayCountry(locBR) + " " + 
            locBR.getDisplayLanguage(locBR));
        System.out.println("");

        // Output:

        // United States English
        // Stati Uniti inglese
        // Stati Uniti inglese

        //  Italian
        //  italiano
        //  italiano

        // Switzerland Italian
        // Svizzera italiano
        // Svizzera italiano
    }
    public static void testNumberFormat() {
        NumberFormat[] formats = {
                NumberFormat.getInstance(),
                NumberFormat.getInstance(Locale.ENGLISH),
                NumberFormat.getInstance(Locale.GERMANY),
                NumberFormat.getNumberInstance(),
                NumberFormat.getNumberInstance(Locale.ENGLISH),
                NumberFormat.getNumberInstance(Locale.GERMANY),
                NumberFormat.getCurrencyInstance(),
                NumberFormat.getCurrencyInstance(Locale.ENGLISH),
                NumberFormat.getCurrencyInstance(Locale.GERMANY)
        };

        for (NumberFormat nf : formats) {
            System.out.println(nf.format(123.4567f));
        }

        // Prints:
        // 123.457
        // 123.457
        // 123,457
        // 123.457
        // 123.457
        // 123,457
        // $123.46
        // ¤123.46
        // 123,46 €
    }
}

Regular Expressions (regex)
  • If you use regex, you'll have to import java.util.regex.*;
  • Regex helps you find text in strings. You "compile" a Pattern class for the "regular expression" you wish to find, create a Matcher class off the resulting pattern for the string you wish to search, then call a regex method on the Matcher class.
  • String.split actually splits on a regex expresion. Thus, to split on a dot ., you have to truss up your statement to say s.split("\\."), so it won't think it's a metacharacter, or an invalid escaped character.
  • You can't create a pattern by saying "Pattern p = new Pattern()" - you have to "compile" the pattern.
  • You can't create a Matcher by saying "Matcher m = new Matcher()" - you must call the "matcher" method against a compiled pattern, to create a matcher.
  • "compile" is a static method of the Pattern class, that compiles the given regular expression into a pattern p.
  • "matcher" is an instance method of the Pattern class, that creates a matcher that will match the given input against this pattern.

    Example:

    import java.util.regex.*;
    
    public class testRegex {
        public static void main(String[] args) {
            String find = "n";
            // Compile the pattern
            Pattern p = Pattern.compile(find);                     
            Matcher m = p.matcher("See if you can find all the n's in this string.");
            // Create the matcher off the pattern
            System.out.printf("Found '%s' at character: ", find);  
            // Find the phrase
            while (m.find())          
                // Start index of the found phrase		
                System.out.printf("%d ", m.start());               
            System.out.println("");
            // Prints:
            // Found 'n' at character: 13 17 28 33 44 
        }
    }
    
Searching the string goes from left to right. Once a character is 'consumed' by being found in a search, it can't be found in another occurrence,
You can look for special characters in the phrase, by using metacharacters. Some metacharacters include:
    \d	Digit
    \s	Whitespace                             
    \w	A word character (letters, digits, or _) 
    .	Any character
You can search for sets of characters using ranges included in brackets, as follows:
    [afg]       Searches for a, f, and g characters.
    [a-g]       Searches for a, b, c, d, e, f, g characters.
    [b-cX-Y]    Searches for b, c, X, Y, Z characters.
    [acex-z]    Searches for all a, c, e, x, y, z characters.
Some other special characters are:
    ^[abc]      Searches for an a, b, or c at the beginning of the line.
    [^abc]      Searches for any character OTHER than a, b, and c.
    $[xyz]      Searches for an x, y, or z at the ending of the line.
    *           Match the preceding element 0 or more times.
    +           Match the preceding element 1 or more times.
    ?           Match the preceding element 0 or 1 time.
By default, the last three statements above are 'greedy' searches, meaning they'll scan the entire string first, and match as many characters as possible. To make them reluctant (non-greedy) searches, suffix them with a ?.
    *?          Reluctant (non-greedy) match the preceding element 0 or more times.
    +?          Reluctant (non-greedy) match the preceding element 1 or more times.
    ??          Reluctant (non-greedy) match the preceding element 0 or 1 time.
Example of greedy vs. non-greedy:
    String:  yyxxxyxx
    Pattern: .*xx		
    Found at char 0 only.
	
    String:  yyxxxyxx
    Pattern: .*?xx
    Found at chars 0 and 4.
Matcher Methods
boolean find() Attempts to find the next subsequence of the input sequence that matches the pattern. This method starts at the beginning of this matcher's region, or, if a previous invocation of the method was successful and the matcher has not since been reset, at the first character not matched by the previous match. If the match succeeds then more information can be obtained via the start, end, and group methods.
int start() Returns the index of the first character matched.
String group() Returns the (possibly empty) input subsequence matched by the previous match. For a matcher m with input sequence s, the expressions m.group() and s.substring(m.start(), m.end()) are equivalent. Note that some patterns, for example a*, match the empty string. This method will return the empty string when the pattern successfully matches the empty string in the input.
int end() Returns the offset after the last character matched.
Regex Example
import java.util.regex.*;

public class testRegex {
  public static void main(String[] args) {
    FindRegex("n", "See if you can find all the n's in this string.");      
    // Found 'n' at character: 13 17 28 33 44 
    
    FindRegex("cdc", "cdcdcdc");  
    // Found 'cdc' at character: 0 4 
    
    // The next line won't compile because it needs a double backslash
    // FindRegex("\d", "0a12b3c456d"); 
    
    FindRegex("\\d", "0a12b3c456d");
    // Found '\d' at character: 0 2 3 5 7 8 9 
    
    FindRegex("\\d\\s", "0 123 a 5d 6\n");
    // Found '\d\s' at character: 0 4 11 
    
    // Search for valid hex strings only - 
    // starting with a 0, followed by x or X, 
    // and containing 1 or more occurrences of [0-9a-fA-F]
    FindRegex("0[xX][0-9a-fA-F]+", "hex string 0xab 0x0102a 0x ox");
    // Found '0[xX][0-9a-fA-F]+' at character: 11 16 
    
    // Find word, even if it's misspelled
    FindRegex("sep[ae]r[ae]te", "separate seperate separete seperete\n");
    // Found 'sep[ae]r[ae]te' at character: 0 9 18 27 
    
    // Find an identifier in a programming language
    ListRegex("[A-Za-z_][A-Za-z_0-9]*.", "public int x = 1;");
    //Pattern '[A-Za-z_][A-Za-z_0-9]*.' found at:
    //    0 public 
    //    7 int 
    //   11 x 
    
    // Find a valid phone number
    String pattern = "[01]?[- .]?(\\([2-9]\\d{2}\\)|[2-9]\\d{2})[- .]?\\d{3}[- .]?\\d{4}";
    ListRegex(pattern, "(360) 807-6299, (360)4262112, 3601234567, 4262040");
    //Pattern '[01]?[- .]?(\([2-9]\d{2}\)|[2-9]\d{2})[- .]?\d{3}[- .]?\d{4}' found at:
    //    0 (360) 807-6299
    //   15  (360)4262112
    //   29  3601234567
    
    // Greedy by default - ate all occurrences
    ListRegex(".*xx", "yyxxxyxx");
    //Pattern '.*xx' found at:
    //    0 yyxxxyxx
    
    // A question mark after the * makes it less greedy.
    ListRegex(".*?xx", "yyxxxyxx");
    //Pattern '.*?xx' found at:
    //    0 yyxx
    //    4 xyxx
    
    // How to find a dot, since dot is a metacharacter.
    FindRegex("\\.", "this.is.a.dotty.line");
    // Found '\.' at character: 4 7 9 15 
  }
  
  public static void FindRegex(String pattern, String searchstring) {
     Pattern p = Pattern.compile(pattern);
    Matcher m = p.matcher(searchstring);
    System.out.printf("Found '%s' at character: ", pattern);  
    while (m.find())                     
      System.out.printf("%d ", m.start());        
    System.out.println("");
    
  }
  
  public static void ListRegex(String pattern, String searchstring) {
     Pattern p = Pattern.compile(pattern);
    Matcher m = p.matcher(searchstring);
    System.out.printf("Pattern '%s' found at:\n", pattern);  
    while (m.find()) {                    
      System.out.printf("  %3d %s\n", m.start(), m.group());   
     }
    System.out.println("");
  }
}

Scanner Class
  • If you use Scanner, you'll have to import java.util.Scanner;
  • Use a scanner when you need to split something very large, and stop partway through based on results.
  • It tokenizes in a loop, allowing you to exit at any time
  • It can convert tokens to their appropriate primitive automatically.
Scanner(File source) Constructs a Scanner that uses the specified file.
Scanner(File source, String charsetName) Constructs a new Scanner that uses the specified file.
Scanner(InputStream source) Constructs a new Scanner that uses the specified input stream.
Scanner(InputStream source, String charsetName) Constructs a new Scanner that uses the specified input stream.
Scanner(Readable source) Constructs a new Scanner that uses the specified source.
Scanner(ReadableByteChannel source) Constructs a new Scanner that uses the specified channel.
Scanner(ReadableByteChannel source, String charsetName) Constructs a new Scanner that uses the specified channel.
Scanner(String source) Constructs a new Scanner that uses the specified string.
boolean hasNext() Returns true if this scanner has another token in its input.
boolean hasNext(Pattern pattern) Returns true if the next complete token matches the specified pattern.
boolean hasNext(String pattern) Returns true if the next token matches the pattern constructed from the specified string.
boolean hasNextXXX() Returns true if the next token in this scanner's input can be interpreted as type XXX, where XXX can be:
	Line
	Boolean
	Byte
	Short
	Int
	Long
	BigInteger
	Float
	Double
	BigDecimal
MatchResult match() Returns the match result of the last scanning operation performed by this scanner.
String next() Finds and returns the next complete token from this scanner.
String next(Pattern pattern) Returns the next token if it matches the specified pattern.
String next(String pattern) Returns the next token if it matches the pattern constructed from the specified string.
XXX nextXXX() Scans the next token of the input as a type XXX, where XXX can be:
	Line
	Boolean
	Byte
	Short
	Int
	Long
	BigInteger
	Float
	Double
	BigDecimal
Scanner Example
import java.util.Scanner;

public class testScanner {
  public static void main(String[] args) {
    testNext("Here is 1 true statement and 2 false ones.");
  }
  
  public static void testNext(String source) {
    // Prints
    //  Here is INT(1) BOOLEAN(true) statement and INT(2) BOOLEAN(false) ones. 
    String s;
    String retval = " ";
    Scanner scanner = new Scanner(source);
    while (scanner.hasNext()) {
      if (scanner.hasNextInt()) {
        int i = scanner.nextInt();
        retval += String.format("INT(%d) ", i);
      } else if (scanner.hasNextBoolean()) {
        boolean b = scanner.nextBoolean();
        retval += String.format("BOOLEAN(%b) ", b);
      } else {
        retval += String.format("%s ", scanner.next());
      }
    }
    System.out.println(retval);
  }
}

Formatted Text - printf
There are three common ways to output formatted text:
  • System.out.printf - Writes formatted output to console
  • System.out.format - Does the same thing as printf
  • String.format - Returns a string
To create a formatted string, use the following syntax:
    String s = String.format(fmt, args);
where fmt is the format string, and args is an array of Object containing the argument(s) to use.

The format string is a string of text that includes additional format specifiers, that tell the system how to print the arguments that follow.

The general format of the format specifier is:

    %[arg_index$][flags][width][.precision]conversionchar
    
	where:

        arg_index - the argument number to print (1-based!)
	   
        flags - is one of:
           -    Left justify the argument
           +    Include a + or - sign with the argument
           0    Pad the argument with zeroes
           ,    Use locale-specific grouping separators (ie, the comma in 5,400)
           (    Enclose negative numbers in parentheses
		   
        width - the minimum number of characters TOTAL to print,
                INCLUDING the decimal point and precision characters!
		
        precision - the number of digits to print after the decimal point
		
        conversionchar - the type of argument you'll be formatting.
           b   boolean
           c   char
           d   integer
           f   floating point
           s   string
Examples:

public class testPrintF {
	public static void main(String... args) {
		String fmt = "%s\n";
		String data = "This is a line.";
		
		// The following two lines do the same thing.
		System.out.format(fmt, data);
		System.out.printf(fmt, data);
		
		// %[arg_index$][flags][width][.precision]conversion char
		
		// Default numbers won't line up
		for (int i = 9; i < 12; i++)
			System.out.format("Line %d\n", i);	
		
		// To line them up, specify the minimum width
		for (int i = 9; i < 12; i++)
			System.out.format("Line %2d\n", i);	
		
		// Floats and doubles are padded with zeros to the precision specified.
		for (double d : new double[]{1.2, 3.4, 5.667, 12.3})
			System.out.printf("%.2f\n", d);
		
		// However, they also won't line up unless you specify the width.
		for (double d : new double[]{1.2, 3.4, 5.667, 12.3, 133.6})
			System.out.printf("%6.2f\n", d);
		
		// Print arguments out of order - 1 BASED
		System.out.printf("%1$d %1$d %3$d %2$d\n", 1, 2, 3);
		
		// Test justification
		System.out.printf("\n%-10d\n%10d\n\n", 52, 52);
		
		// Print a negative number a few different ways.
		double x = -4332.678;
		System.out.printf("$%(,12.2f\n", x);
		System.out.printf("$%(,012.2f\n", x);
		System.out.printf("$%+12.2f\n", x);
	}
}
The output of the above program is:
This is a line.
This is a line.
Line 9
Line 10
Line 11
Line  9
Line 10
Line 11
1.20
3.40
5.67
12.30
  1.20
  3.40
  5.67
 12.30
133.60
1 1 3 2

52        
        52

$  (4,332.68)
$(004,332.68)
$    -4332.68