It can seem to be sensible to make a method final while youre designing a class. You might feel that no one could possibly want to override your methods. Sometimes this is true.
But be careful with your assumptions. In general, its difficult to anticipate how a class can be reused, especially a general-purpose class. If you define a method as final, you might prevent the possibility of reusing your class through inheritance in some other programmers project simply because you couldnt imagine it being used that way.
The standard Java library is a good example of this. In particular, the Java 1.0/1.1 Vector class was commonly used and might have been even more useful if, in the name of efficiency (which was almost certainly an illusion), all the methods hadnt been made final. Its easily conceivable that you might want to inherit and override with such a fundamentally useful class, but the designers somehow decided this wasnt appropriate. This is ironic for two reasons. First, Stack is inherited from Vector, which says that a Stack is a Vector, which isnt really true from a logical standpoint. Second, many of the most important methods of Vector, such as addElement( ) and elementAt( ), are synchronized. As you will see in Chapter 11, this incurs a significant performance overhead that probably wipes out any gains provided by final. This lends credence to the theory that programmers are consistently bad at guessing where optimizations should occur. Its just too bad that such a clumsy design made it into the standard library, where everyone had to cope with it. (Fortunately, the Java 2 container library replaces Vector with ArrayList, which behaves much more civilly. Unfortunately, theres still new code being written that uses the old container library.)
Its also interesting to note that Hashtable, another important Java 1.0/1.1 standard library class, does not have any final methods. As mentioned elsewhere in this book, its quite obvious that some classes were designed by completely different people than others. (Youll see that the method names in Hashtable are much briefer compared to those in Vector, another piece of evidence.) This is precisely the sort of thing that should not be obvious to consumers of a class library. When things are inconsistent, it just makes more work for the useryet another paean to the value of design and code walkthroughs. (Note that the Java 2 container library replaces Hashtable with HashMap.)