THE Java™ Programming Language, Fourth Edition

(Jeff_L) #1

others. If you make anything final, be sure that you want to create these restrictions.


In many cases, you can achieve the security of marking a whole class final by leaving the class extensible
and instead marking each method in the class as final. In this way, you can rely on the behavior of those
methods while still allowing extensions that can add functionality without overriding methods. Of course,
fields that the final methods rely on should be final or private, or else an extended class could change
behavior by changing those fields.


Another ramification of final is that it simplifies optimizations. When a non-final method is invoked, the
runtime system determines the actual class of the object, binds the method invocation to the correct
implementation of the method for that type, and then invokes that implementation. But if, for example, the
getName method was final in the Attr class and you had a reference to an object of type Attr or any
extended type, it can take fewer steps to invoke the method. In the simplest case, such as getName, an
invocation can be replaced with the actual body of the method. This mechanism is known as inlining. An
inlined method makes the following two statements perform the same:


system.out.println("id = " + rose.name);
System.out.println("id = " + rose.getName());


Although the two statements are equally efficient, a getName method allows the name field to be read-only
and gives you the benefits of abstraction, allowing you to change the implementation.


The same optimizations can be applied to private and static methods, because they too cannot be overridden.


Some type checks become faster with final classes. In fact, many type checks become compile time checks,
and errors can be caught earlier. If the compiler encounters a reference to a final class, it knows that the
object referred to is exactly that type. The entire class hierarchy for that class is known, so the compiler can
check whether any use is valid or invalid. With a non-final reference, some checks can happen only at run
time.


Exercise 3.4: Which methods (if any) of Vehicle and PassengerVehicle might reasonably be made
final?


3.7. Abstract Classes and Methods


An extremely useful feature of object-oriented programming is the concept of the abstract class. Using
abstract classes, you can declare classes that define only part of an implementation, leaving extended classes
to provide specific implementation of some or all of the methods. The opposite of abstract is concretea class
that has only concrete methods, including implementations of any abstract methods inherited from
superclasses, is a concrete class.


Abstract classes are helpful when some of the behavior is defined for most or all objects of a given type, but
other behavior makes sense only for particular classes and not for a general superclass. Such a class is
declared abstract, and each method not implemented in the class is also marked abstract. (If you need
to define some methods but you don't need to provide any implementation, you probably want to use
interfaces, which are described in Chapter 4.)


For example, suppose you want to create a benchmarking harness to provide an infrastructure for writing
benchmarked code. The class implementation could understand how to drive and measure a benchmark, but it
couldn't know in advance which benchmark would be run. Most abstract classes fit a pattern in which a
class's particular area of expertise requires someone else to provide a missing piecethis is commonly known as

Free download pdf