As we saw in Chapter 2, there is a polymorphic type Object which can hold a reference to any object. As you may have surmised from the fact that Object starts with an upper-case letter, there is in fact an Object class. The Object class is an ancestor of every other class. A very small part of the Object family tree is shown in Figure 3-10.
Figure 3-10. The Object class and a few of its descendants.
Since we extend Object so often, Java allows us to omit extends Object from the top of a class. If a class doesn't say that it extends some other class, it extends Object.
Methods of the Object Class
While we usually have to cast in order to invoke a method on a variable of type Object, the Object class does have a few methods of its own. These are usually overridden, but they are guaranteed to be present, so they can be invoked without casting.
The Object class has a constructor which takes no arguments. It is legal, though not terribly useful, to create an instance of the Object class:
Object it = new Object();
The equals() method for the Object class behaves exactly like ==. If we define a subclass of Object and fail to override equals(), then for two instances a and b of this subclass, a.equals(b) exactly when a == b. It is especially important to provide a valid equals() method for classes which implement the Comparable interface (Chapter 8).
In order to override the equals() method, we must provide a method with the same signature:
public boolean equals(Object that)
If we use a different argument type, we are not overriding the method, but merely overloading the name with a method accepting a different argument type. The version from Object is still inherited. Since an instance of any class other than Object might work as an argument for either version, this can cause unexpected behavior.
As we mentioned earlier, the method getClass() returns a representation of an object's class. This happens automaticallythere is no need to override getClass().
The toString() method for the Object class returns a String like:
java.lang.Object@9c26f5
The part to the left of the @ is the class of the instance. The part to the right has to do with the location in memory where the instance is stored and varies from one instance to another. If we fail to override toString() in a subclass, this method is smart enough to use the name of the subclass. For example, if we omitted the toString() method from Light, printing an instance of Light would produce a String like:
Light@4d3343
The last important method of the Object class, hashCode(), is discussed in Chapter 11. For now, we note that equals() and hashCode() interact. If a class overrides one of these methods, it should override both of them.
Implicit Constructors
If the Light class implicitly extends Object, then shouldn't its constructor begin by invoking a constructor from Object? Yes, and while it is not explicit, the constructor does this. Since it is so common for constructors to begin with
super();
Java allows us to omit this line. For example, we could have omitted line 9 in Figure 3-4.
We can go even farther than this. Every class that does not provide an explicit constructor gets an implicit zero-argument constructor which does nothing but invoke the zero-argument super constructor. This means that we could have left out the constructors in the Cram class (Figure 3-1) and the FlashingColoredLight class (Figure 3-6).
Exercise
3.6 |
Through experimentation, determine what happens if we print an array of ints. What about an array of Lights? What about a multidimensional array? |
3.7 |
Make the superclass and constructor for the Thingamabob class (Figure 3-11) explicit. |
Figure 3-11. The Thingamabob class for Exercise 3.7.
1 public class Thingamabob { 2 3 private int x; 4 5 public void setX(int x) { 6 this.x = x; 7 } 8 9 } |
3.8 |
Consider the classes Doohickey (Figure 3-12) and Whatsis (Figure 3-13). Explain why Whatsis does not compile. |
Figure 3-12. The Doohickey class for Exercise 3.8.
1 public class Doohickey extends Thingamabob { 2 3 public Doohickey(int x) { 4 super(); 5 setX(x); 6 } 7 8 } |
Figure 3-13. The Whatsis class for Exercise 3.8.
1 public class Whatsis extends Doohickey { 2 } |
Packages and Access Levels |
Part I: Object-Oriented Programming
Encapsulation
Polymorphism
Inheritance
Part II: Linear Structures
Stacks and Queues
Array-Based Structures
Linked Structures
Part III: Algorithms
Analysis of Algorithms
Searching and Sorting
Recursion
Part IV: Trees and Sets
Trees
Sets
Part V: Advanced Topics
Advanced Linear Structures
Strings
Advanced Trees
Graphs
Memory Management
Out to the Disk
Part VI: Appendices
A. Review of Java
B. Unified Modeling Language
C. Summation Formulae
D. Further Reading
Index