The Object
SuperclassJ8 Home « The Object
Superclass
We finish the section with two lessons looking at the Object
superclass, the 'daddy' of all objects. To explain what we mean by the last sentence, we need to first look back to the first Java class we wrote on the site,
the Hello.java
class:
package info.java8;
public class Hello {
public static void main (String[] args) {
System.out.println("Hello World");
}
}
Unbeknown to us, this simple program was implicitly extended by the compiler, in fact every program we write has an implicit superclass called Object
. How can this be though?
Looking back to earlier lessons in the section how can our Garbage
class extend Truck
and Object
, we know we can only extend one class. Well the compiler
just travels up the inheritance tree and tries to extend our Truck
class. The Truck
class extends the Vehicle
class so the compiler travels up the tree again. The Vehicle
class extends nothing so the compiler implicitly extends the Vehicle
class with Object
. What this means for us is that we get to inherit the methods of Object
which we will talk
about as we go through this lesson. For now, we just need to know that we always inherit from Object
at the top of any hierarchy we create. Before we look at the methods of the Object
class
lets list some points about Object
:
- Any class that doesn't implicitly extend another class, is implicitly extended by the compiler to extend
Object
. Object
is a concrete class so we can create objects of typeObject
.- Every class inherits the non-final methods of
Object
and these methods can be overridden. - We can use
Object
as a polymorphic type for methods that need to work with objects of any type.- So if we can use
Object
as a polymorphic type, why not useObject
with all our methods, parameters and return types? There are two very good reasons not to do this:- Java is a strongly typed language and as such cares about the type of the variables we declare. As we know whenever we declare a variable in Java, we have to give it a type, or the compiler complains when
we come to compile the code. If we made every parameter and return type
Object
bang goes our type-safety. Instead of catching errors at compile time, we may run code for months before we get a runtime error, or even worse not notice an error at all, not a pleasant prospect. - Inheritance, remember this only works up the inheritance tree as explained in inheritance method invocation. So if we made everything reference
Object
, what happens when we try to use theload()
method from ourVehicle
classes on theObject
reference type? The compiler doesn't allow it asObject
knows nothing of subclass methods unless they have been overridden. Therefore the only methods that can be called onObject
are its own methods, or overrides thereof.
- Java is a strongly typed language and as such cares about the type of the variables we declare. As we know whenever we declare a variable in Java, we have to give it a type, or the compiler complains when
we come to compile the code. If we made every parameter and return type
Object
reference type polymorphically, and on occasions this is exactly what we want to do, it comes with a price. - So if we can use
Object
Methods Overview Top
The table below shows the declarations of all the methods in the Object
class:
Method Declaration | Description |
---|---|
Discussed in this lesson | |
protected void finalize() | Called by the garbage collector on an object before that object is discarded. |
public final Class<? extends Object> getClass() | Obtains and returns the runtime class of an object. The <? extends Object> syntax is an example of a generic type which is discussed in the Generics section. |
public String toString() | Returns a string description of the object. |
Discussed in the Checking Object Equality Lesson | |
public boolean equals(Object obj) | Indicates whether another object is equal to the invoking object. |
public int hashCode() | Returns the hash code value associated with the object. |
Discussed in the Concurrency Section | |
public final void notify() | Wakes up a single thread that is waiting on the invoking object's lock. |
public final void notifyAll() | Wakes up all threads that are waiting on the invoking object's lock. |
public final void wait() | Current thread is put into a wait state until another thread invokes the notify() or notifyAll() method for this object. |
public final void wait(long timeout) | Current thread is put into a wait state until either another thread invokes the notify() or notifyAll() method for this object, or a specified amount of time has elapsed. |
public final void wait(long timeout, int nanos) | Current thread is put into a wait state until another thread invokes the notify() or notifyAll() method for this object, or a specified amount of time has elapsed, or a certain amount of real time has elapsed. |
Not discussed | |
protected Object clone() | Creates and returns a shallow copy of this object. |
We will go through the first three methods in much greater detail as we go through this lesson and look at the equals()
and hashCode()
method in the Checking Object Equality lesson. Use the links in the table above to go the Concurrency section for more information on the other Object
methods
we discuss on the site. For more information on the clone()
method follow the link below.
Java Documentation Top
As mentioned in the first two sections Java comes with very rich documentation. The following link will take you to the online version of documentation for the JavaTM 2 Platform Standard Edition 5.0 API Specification.
Take a look at the documentation for the Object
class which you can find by scrolling down the lower left pane and clicking on Object. You will go back to this documentation time and time again so if you haven't done so already I suggest adding this link to your browser's favourites toolbar for fast access.
The finalize()
Method Top
- The
finalize()
method is only ever invoked once, for any given object, by theJVM
.
The finalize()
method of the Object
class is called by the garbage collector on an object before that object is discarded. The finalize method in the Object
class doesn't execute any specific tasks, but gives us the opportunity to override. We may want to do this to clear up any resources held by an object such as closing a file used by it.
We have no control over when the garbage collector runs as this is in the control of the JVM
. The garbage collector runs its collection efficiently and this means it usually runs when there
are a lot of objects to discard.
Overriding finalize()
Top
To see an overridden finalize()
method in action we are going to have to instantiate a lot of objects and then make these objects eligible for garbage collection:
package info.java8;
/*
Class to show an overridden finalize() method in action
*/
public class Finalize {
private int i;
Finalize(int i) {
this.i = i;
}
/*
Instantiate a Finalize object and immediately descope it
*/
public void CreateFinalize(int i) {
Finalize f = new Finalize(i);
}
/*
Overridden finalize() method
*/
protected void finalize() {
System.out.println("The finalize() method called on object: " + i);
}
/*
You may need to change the iterator to get this to work!
*/
public static void main (String[] args) {
Finalize f = new Finalize(0);
for (int i=1; i < 300000; i++) {
f.CreateFinalize(i);
}
}
}
Save, compile and run the Finalize
class in directory c:\_OOConcepts in the usual way.
The above screenshot shows the output of running our Finalize
class on my machine. You may have to increase the iterator within the for
loop to get it to work.
The getClass()
Method Top
The getClass()
method of the Object
class obtains and returns the runtime class of an object, or put another way the object that was instantiated.
package info.java8;
/*
Test Class for the getClass() method
*/
public class GetClassTest {
public static void main (String[] args) {
Vehicle car = new Car();
System.out.println(car.getClass());
Bus bus = new Bus();
System.out.println(bus.getClass());
}
}
Save, compile and run the file in directory c:\_OOConcepts in the usual way.
The above screenshot shows the output of running our ATest
test class. As you can see the method returns the class of the instantiated object.
The toString()
Method Top
The toString()
method of the Object
class returns a string description of the object which consists of the name of the class, the @
symbol and the unsigned hexadecimal
representation of the hash code of the object. The official documentation from Oracle encourages us to override this method in our subclasses, which as we now know, are all subclasses of Object
. Before we
create an override lets look at the output of the toString()
method we inherit from Object
:
package info.java8;
/*
Test Class for the Object toString() method
*/
public class ToStringTest {
public static void main (String[] args) {
Carrier carrier = new Carrier(10, 20);
System.out.println(carrier.toString());
}
}
Save, compile and run the file in directory c:\_OOConcepts in the usual way.
The above screenshot shows the output of running our ToStringTest
test class. As you can see the method returns the class of the instantiated object, the @
symbol and a number, not very
meaningful.
Overriding toString()
Top
What we need to do is override the Object toString()
method in our Carrier
class to give us some more information about the object state of instances we create:
package info.java8;
/*
A Carrier class
*/
public class Carrier {
...
/*
A Carrier class
*/
public String toString() {
String strVal = "[" + this.people + ", " + this.cost + "]";
}
}
After adding the toString
override to the Carrier
class, save and compile it and rerun the ToStringTest
test class in directory c:\_OOConcepts in the usual way.
The above screenshot shows the output of running our ToStringTest
test class. We have overridden the Object toString()
method in our Carrier
class with something more meaningful to the class in question.
Related Quiz
OO Concepts Quiz 19 - The Object
Superclass
Lesson 19 Complete
In this lesson we took a first look at the Object
object, the daddy of all objects.
What's Next?
We finish the section on OO Concepts by looking at object equality and how to use it correctly in our classes.