The following program defines a class of bank account objects and illustrates some of the most important features of Java classes. Each new Account object has two "instance variables", namely a String containing the name of the owner and an integer value containing the current balance in the account. In practice such objects might be much more elaborate than this but this is sufficient for the purpose of an example.

The main method at the end of the class is included for test purposes. It shows a example of how the class might be used. If you compile and run this program by itself it is the main method that will be executed. Once you are confident that this class is performing the way you want it to you can make use of the methods in this class in other more elaborate programs which are unlikely to find this particular main method useful. However, there is no need to remove the main method once the program is working. It does not occupy much space.

The main method begins by creating two new Account objects and storing references to the new objects in the variables laura and james. The process of creating new objects is rather involved. The system must find space to hold an object. The amount of space depends on the number and type of the instance variables. If it is unable to find enough space an error will occur. Otherwise the space is "zeroed" which has the effect of setting all the numeric instance variables to zero (and any character instance variables to '\u0000' and any boolean instance variables to false and all reference variables to null). After the new object is zeroed the system looks for a "constructor" to execute. A contructor is like a method. It is used to initialize instance variables to non-zero values. Technically, the designers of the Java language say that constructors are not methods. This is because they do not return any value - not even void! But many programmers consider them to be special methods which are distinguished by having the same name as the class and no return value.

class Account has two constructors both with the name "Account". The first one takes two parameters (name and initialAmount) and uses them to initialize the appropriate instance variables. The second constructor is shorter. It takes a name only to initialize the owner field. The balance instance variable is left as zero.

Programmers often use the term "c-tor" as an abbreviation for constructor. The main method uses the first c-tor for the laura object and the second c-tor to initialize the james object.

public class Account {
  // instance variables
  String owner;     // the name of the owner
  int balance;          // current balance in pennies (not public)

  // constructors - new Accounts are created with a given name and
  // either a specified initial balance or the default value of 0
  public Account ( String name, int initialAmount) {
    owner = name;
    balance = initialAmount;
  }
  public Account ( String name ) { owner = name; /* balance = 0; */ }

  // methods
  public void deposit  (int amount) { balance += amount; }

  public void withdraw (int amount) { balance -= amount; }

  public String toString () {
    return "Account with balance: " + balance + " owned by " + owner;
  }

  public static void main ( String argv[] ) {
    Account laura = new Account("Laura",100), 
	    james = new Account("James");
    // allocates 2 Account objects each initialized by different ctor
    // The accounts are initialized with balances of 100 and 0,
    respectively
    System.out.println( laura );
    james.deposit (500);            // now james.balance should be 500
    System.out.println( james );    // output: james.toString()
    laura.deposit (300);
    System.out.println( laura );
    james.withdraw (600);           // now "in the red"
    System.out.println( james );       
  }
}
/* Output:
Account with balance: 100 owned by Laura
Account with balance: 500 owned by James
Account with balance: 400 owned by Laura
Account with balance: -100 owned by James
*/

Note that we use classes to create many new objects. This particular main method creates two new objects. This means that when we refer to an instance variable such as "balance" we must be careful to specify both the object and the instance variable. The syntax is similar to that in many other programming languages. For example, we refer to that balance field in the object laura as laura.balance. Similarly james.name refers to the name field in the object james. To see if Laura has more in her account than James we could use, for example:

   if ( laura.balance > james.balance ) ... 

Looking back at the main method again we see the statement: james.deposit (500); and later laura.deposit(300); We expect these statements to have the effect of increasing james.balance by an amount of 500 and laura.balance by an amount of 300. The way is done is interesting. Looking for a method called deposit we find:

   public void deposit  (int amount) { balance += amount; }

The "+=" means that we want the add the amount to the balance. But which balance: james.balance or laura.balance ? Java is similar to C++ in the way this is resolved. Whenever we refer to an instance variable such as balance without specifying which object, the system treats this as if we had written this.balance instead. The reference this refers to whatever object appears on the left in calling program (which is james in the first example above). Thus the statement "james.deposit (500);" causes the deposit method to be executed with this referring to the same object that james refers to. Also the parameter amount is "bound" to the value 500 while the body of the method is executed. The statement balance += amount; which was expanded to this.balance += amount; has the effect of adding 500 to james.balance. Similarly, the statement laura.deposit(300); causes the deposit method to be executed with this referring to laura and amount bound to the value 300. This has the effect of increasing laura.balance by 300.

The withdraw method is similar to the deposit method. The unqualified reference to the variable "balance" is treated as if we had written "this.balance" where this is whatever object is on the left in the calling method. Executing this method causes the corresponding balance to be reduced by a certain amount.

The only remaining method to consider in this class is the toString() method. Objects in Java are stored internally in binary form (zero and one bits) which are convenient for fast execution by a machine but very unsuitable for human beings to understand! If you want to display an object so that humans can understand it then you should provide a method called toString() which returns a String of characters. Notice that the main method does not refer to the toString() method directly. Instead it executes the println method of the object System.out. The print and println methods are very simple. They take any object provided as an argument and convert it to a String using the toString() method and then print out the characters in the String. The println method also outputs end-of-line characters appropriate for the system that is being used.

If you study the output from the main method attached to the end of the example you will see the results produced by the toString() method.

The toString method is mainly used for printing objects but not only for that purpose. It is fairly common to define a method to test if two objects are equal by testing if the corresponding Strings returned by the toString() method are equal.