Table of Contents
So far, we’ve looked at instance variables and methods — that is, variables and methods associated with a specific instance of a class.
However, it is possible to associate both variables and methods with the class itself. These are known as class variables and class methods.
Class vs. Instance Variables
Consider the class BankAccount:
class BankAccount
{
// Instance methods
double deposit(double amount)
{
m_balance += amount;
return m_balance;
}
// Instance variables
String m_holder;
double m_balance;
}
For each instance of the BankAccount class, there is a separate and independent set of instance variables:
- m_holder
- m_balance
But what if we wanted to have a set of variables that are related to all instances of that class? For example, a bank might wish to keep track of:
- Total number of accounts
- Total deposits for all accounts
- Total withdrawals for all accounts
for all BankAccounts.
We can do this by defining:
- A set of class variables (also known as static variables, or static data members),
- A set of associated class methods (also known as static methods).
For example:
class BankAccount
{
// Constructors
BankAccount() { this("", 0.0); }
BankAccount(String name) { this(name, 0.0); }
BankAccount(String name, double balance)
{
m_holder = name; m_balance = balance;
m_count++;
}
// Instance methods
// (NOTE: I'm only using a finalize() method
// so that I can keep the instance counts
// straight for this very simple example.
// It's still not recommended unless you
// really know what you're doing.)
protected void finalize() throws Throwable
{
super.finalize();
m_count--;
}
public String getHolder()
{ return m_holder; }
public double getBalance()
{ return m_balance; }
public double deposit(double amount)
{
m_balance += amount;
m_totalDeposits += amount;
return m_balance;
}
public double withdraw(double amount)
{
m_balance -= amount;
m_totalWithdrawals += amount;
return m_balance;
}
// Class methods
public static int count()
{ return m_count; }
public static double totalDeposits()
{ return m_totalDeposits; }
public static double totalWithdrawals()
{ return m_totalWithdrawals; }
public static void main(String[] argv)
{
BankAccount bh
= new BankAccount("Bryan Higgs",
1000000.00);
System.out.println("Account of: " + bh.getHolder());
System.out.println("Balance : " + bh.getBalance());
BankAccount ep
= new BankAccount("Elvis Presley",
100000000.00);
System.out.println("Account of: " + ep.getHolder());
System.out.println("Balance : " + ep.getBalance());
double amount = 15000.00; // I'm not greedy!
ep.withdraw(amount);
bh.deposit(amount);
System.out.println("Number of accounts : " +
BankAccount.count());
System.out.println("Total Deposits : " +
BankAccount.totalDeposits());
System.out.println("Total Withdrawals : " +
BankAccount.totalWithdrawals());
}
// Instance variables
String m_holder;
double m_balance;
// Class variables
static int m_count = 0;
static double m_totalDeposits = 0.0;
static double m_totalWithdrawals = 0.0;
}
Note:
- The keyword static is used to specify that a member is a class member, rather than an instance member.
- There is exactly one set of class variables for a given class.
- Class variables exist whether instances of that class exist or not.
- Class variables should be initialized in the class itself, not normally in a class constructor (Why?)
- Class variables may be accessed without qualification within their class, or by explicit class name qualification outside their class.
- Class methods do not have an implicit this variable (Why?)
- Class methods may access class variables, but not instance variables (Why?)
- Instance methods may call class methods, but not (usually) the other way around (Why?)
Usage
Class variables and class methods are used extensively in Java
Here are some examples of class variables:
- PI — in the Java Math package
- out — in the Java System package
Remember System.out.print() ???
Here are some examples of class methods:
- sqrt — in the Java Math package
- exit — in the Java System package
Initialization
Class variables may be initialized in the class definition (just like instance variables).
Class variables declared as final must be initialized in the class definition (just like instance variables).
Note that:
- Class variables are initialized when the class is first loaded
while:
- Instance variables are initialized when the class instance is created.
Static Initializers
Sometimes we need to initialize things in a way that cannot be handled using such simple initializers.Instance variables have constructor methods to accomplish this.
Class variables need a different mechanism: static initializers
For example:
class Primes
{
...
private static int nextPrime(int startFrom)
{
/* ... */
}
...
//// Data ////
private static int knownPrimes = new int[4];
static
{
knownPrimes[0] = 2;
for (int i = 1; i < knownPrimes.length; i++)
knownPrimes[i] = nextPrime(knownPrimes[i-1]);
}
}
A static initializer is like a class method, except:
- It has no name
- It accepts no arguments
- It returns no value
There can be any number of static initializers — they are executed in lexical order when the class is loaded.
Static initializers are used, among other places, in classes that implement native methods (much later…).
Initialization Blocks
You can also have an initialization block that does not have a static keyword prefix. It allows you to initialize instance fields, or to execute arbitrary code at instance initialization:
public class InitializerTest
{
public static void main(String[] args)
{
InitializerTest test1 = new InitializerTest();
InitializerTest test2 = new InitializerTest();
}
// Initialization block
{
System.out.println("Executing initialization block");
System.out.println("Count now " + ++m_count);
}
static int m_count = 0;
}
which produces:
Executing initialization block Count now 1 Executing initialization block Count now 2
There are a number of potentially useful applications of this technique.
