the "Template Method" pattern. In many cases the expertise methods are good candidates for being final so
that the expertise cannot be compromised in any way. In this benchmarking example, the missing piece is
code that needs to be benchmarked. Here is what such a class might look like:
abstract class Benchmark {
abstract void benchmark();
public final long repeat(int count) {
long start = System.nanoTime();
for (int i = 0; i < count; i++)
benchmark();
return (System.nanoTime() - start);
}
}
Any class with any abstract methods must be declared abstract. This redundancy helps the reader
quickly see that the class is abstract without scanning to see whether any method in the class is declared
abstract.
The repeat method provides the benchmarking expertise. It can time a run of count repetitions of the
benchmark. The method System.nanoTime returns a timestamp in nanosecondssee page 665. By
subtracting the starting time from the finishing time you get an approximation of the time spent executing the
benchmark. If the timing needs become more complex (perhaps measuring the time of each run and
computing statistics about the variations), this method can be enhanced without affecting any extended class's
implementation of its specialized benchmark code.
The abstract method benchmark must be implemented by each subclass that is not abstract itself.
This is why it has no implementation in this class, just a declaration. Here is an example of a simple
Benchmark extension:
class MethodBenchmark extends Benchmark {
/* Do nothing, just return. /
void benchmark() {
}
public static void main(String[] args) {
int count = Integer.parseInt(args[0]);
long time = new MethodBenchmark().repeat(count);
System.out.println(count + " methods in " +
time + " nanoseconds");
}
}
This class times how long it takes to invoke an empty method benchmark, plus the loop overhead. You can
now time method invocations by running the application MethodBenchmark with the number of times to
repeat the test. The count is taken from the program arguments and decoded using the Integer class's
parseInt method on the argument string, as described in "String Conversions" on page 316.
Any class can override methods from its superclass to declare them abstract, turning a concrete method
into an abstract one at that point in the type tree. This technique is useful, for example, when a class's
default implementation is invalid for a part of the class hierarchy.
You cannot create an object of an abstract class because there would be no valid implementation for some
methods that might well be invoked.