Before the questions, make sure you can: explain what a static (class) variable is and why
it is shared; predict the output of a program that mixes static counters with instance data;
state precisely what a static method may and may not touch; design a utility class and a
public static final constant; decide, for a given member, whether it should be static;
and describe a program's decomposition into classes and methods using the vocabulary of cohesion
and coupling.
Instance members versus class members
| Instance member | Class (static) member |
|
|---|---|---|
| Belongs to | one object | the class itself |
| Copies | one per object | exactly one, shared by all objects |
| Accessed through | an object: obj.field |
the class: ClassName.field |
| Created when | the object is created | the class is loaded, before any object exists |
public class Student {
private static int count = 0; // ONE counter for the whole class
private final int id; // one id per object
public Student() { count++; id = count; }
public static int getCount() { return count; } // no object needed
public int getId() { return id; } // needs an object
}
After creating three students, Student.getCount() is 3 while each object reports its own
id. A static field is the right tool for exactly this: information about the class as a
whole (how many exist, a shared rate, a next-available number).
What a static method may touch
A static method runs without a calling object, so:
- it may use
staticfields and call otherstaticmethods directly; - it may not use instance fields or call instance methods directly, and it has no
this; - it may use an object it is given or creates:
s.getId()insidemainis fine, becausessupplies the missing object.
An instance method, on the other hand, may use both instance and static members. This
asymmetry — instance to static is allowed, static to instance is not — is worth writing on the
first page of your revision notes.
Constants and utility classes
public class TaxUtil {
public static final double VAT = 0.19; // class constant
private TaxUtil() { } // prevent instantiation (optional)
public static double withVat(double amount) { return amount * (1 + VAT); }
public static double vatOf(double amount) { return amount * VAT; }
}
// used as TaxUtil.withVat(100), never new TaxUtil()
public static final is the standard way to write a constant that belongs to a class: one
copy, readable everywhere, impossible to modify. Math is the archetype of a utility class,
and the reason you never write new Math().
main is static, and what follows from it
main is static because the JVM must call it before any object of the class exists. That
is why a program that puts real work in instance methods must begin with
new SomeClass().run(); or equivalent, and why calling an instance method directly from
main does not compile.
Designing the classes themselves
- Top-down decomposition. Write the main task as a sequence of named steps, then implement each step as a method, splitting again whenever a method stops fitting on a screen or stops doing one thing.
- Cohesion (high is good): every member of a class belongs to the same idea. A class that stores a student and formats HTML and reads files has low cohesion.
- Coupling (low is good): classes depend on each other as little as possible, and through methods rather than through exposed fields.
- One responsibility per class, one job per method. A method whose comment needs the word “and” is usually two methods.
- Driver separation. Keep
mainthin: it creates objects and calls methods.
Documenting and testing
Javadoc comments (/** ... */ with @param, @return) document the contract of
a method: what it expects and what it guarantees. Test each method as soon as it is written, with
ordinary values, boundary values (0, 1, the first and last index) and invalid values. Debugging by
println is legitimate; debugging by guessing is not.
- One
staticfield exists per class, whatever the number of objects. staticcannot reach instance members directly; instance can reachstatic.public static finaldeclares a class constant.- A utility class has no state worth instantiating.
- High cohesion, low coupling, thin
main.
- Making a field
static“to fix” a compile error inmain: every object then shares one value, which is almost never what was intended. - Using
thisinside astaticmethod. - Declaring a counter as an instance variable and wondering why it is always 1.
- Writing
new Math()ornew TaxUtil().
Ready? Close the notes and practise.
36 questions. Predict the output before you check — that is the skill the exam measures.