In this article, we will see what an abstract class in Java is and how to use one.
Table of Contents
1. What Is an Abstract Class in Java?
In Java, an abstract class is a class that is used as a prototype for other classes. Because of their special purpose, they do have some characteristics that differentiate them from non-abstract classes. Let’s see the main characteristics of an abstract class in Java:
- We cannot instatiate an abstract class, because it’s a blueprint for other classes. As a result, we cannot create an object of an abstract class, using the
new
keyword. - In order to define a class as abstract, we use the
abstract
keyword. - An abstract class can have methods that are either also abstract or non-abstract (more on abstract methods in the following subsection).
- Despite not being able to create an object from an abstract class, we can have constrcuctors.
- They cannot be
final
because the purpose of an abstract class is to be extended by a child class. - Finally, they can have
static
methods ,as well as non-static fields. This rule also aplies for class fields, as they can be either static or non-static, just like in non-abstract classes (remember that, on the other hand, the fields of interfaces are alwayspublic static final
).
2. Abstract Methods
Similar to classes, there are also abstract methods, which are methods without implementation (so they don’t have a body). The following characteristics are true for abstract methods:
- Abstract methods are also delcared with the
abstract
keyword, just like abstract classes. - Instead of a body, we use a semicolon (
;
) at the end of its signature, instead of an opening curly brace ({
). - An abstract method can only exist in an abstract class. If the class is not abstract, no method can be abstract. On the other side, as previously noted, an abstract have may have abstract methods, but it may also not.
- Abstract methods cannot be
final
because a child class must provide an implementation for it. - Additionally, an abstract method cannot be
private
because it would be inaccessible to other classes.
3. An Example of an Abstract Class
Let’s see those characteristics in action. We have created an abstract class, Animal
which has the following fields and methods:
private static int animalsBorn
: a counter that shows how many animals there are. Notice that because it’sstatic
, all classes that extend theAnimal
class share the same counter.Animal()
: the constructor of the abstract class. This will be automatically called whenever a child class is created. Inside the constructor we print a message indicating the creation of an animal and, also, increase theanimalsBorn
by one. The reason we define a constructor for an abstract class (that cannot create object on its own) is to, perhaps, initialize some fields whenever it’s called by a child class.abstract void talk()
: an abstract method that each child class can implement differently, since we can’t know the sound of an animal without knowing what kind of animal it is first.public void run()
: a regular method that is available to all children classes. It prints a message that describes that the animal is running.public static final int getTotalAnimalsBornNumber()
: a static getter of theanimalsBorn
counter. Notice that because it’sfinal
no other subclass can override it with its own implementation, which is something we want in this scenario.
abstract class Animal { // The total number of animals that exist across all usages of Animal abstract class private static int animalsBorn = 0; // Whenever a new child class is created, the counter of Animal increases by one Animal() { System.out.println("A new animal is born."); animalsBorn++; } // the sound an animal can make that's different between animals abstract void talk(); // regular method, common to all animals public void run() { System.out.println("Running like the wind!"); } // getter for animalsBorn, unrelated to a specific animal (belongs to the class not the object, therefore static) public static final int getTotalAnimalsBornNumber() { return animalsBorn; } }
4. An Example of a Class That Extends an Abstract Class
Moving on with our previous example, we can now define two animals, as such:
class Dog extends Animal { @Override void talk() { System.out.println("The dog goes woof-woof!"); } } class Cat extends Animal { @Override void talk() { System.out.println("The cat goes meowww!"); } }
We have created a Dog
and a Cat
class that each extends the Animal
abstract class. Then, each class implements talk()
in its own way. For a Dog
this method makes the animal bark, and for a Cat
it makes it meow.
Since both of these classes are extending Animal
they must implement the talk()
method. If we didn’t want to implement that method, we could do either of the two:
- Override the method but provide an empty body to it, effectively doing nothing.
- Or, declare the child class abstract as well.
5. Putting Everything Together
Finally, let’s see how we can use all those classes together:
class JavaAbstractClassAndMethodsExampleClass { public static void main(String[] args) { Animal animal = new Dog(); // same as Dog newDog = new Dog(); animal.talk(); animal.run(); System.out.println(); animal = new Cat(); // same as Cat newCat = new Cat(); animal.talk(); animal.run(); System.out.println("\nTotal animals: " + Animal.getTotalAnimalsBornNumber()); } }
The output is:
A new animal is born. The dog goes woof-woof! Running like the wind! A new animal is born. The cat goes meowww! Running like the wind! Total animals: 2
Let’s see what happened:
- Line 4: We create a new
Dog
object. TheAnimal animal
means that we can create either aDog
or aCat
object. Whatever is after the equals sign (=
) indicates the implementation (and, thus, the methods) that will be used when we run the program. In this case, anAnimal
has access to the methods ofDog
. In this line, the constructorAnimal()
is also called. - Lines 5-6: Because the
animal
is aDog
, thetalk()
will make the animal bark. Therun()
is independent of what theanimal
is. - Line 10: The
animal
is now aCat
, so it has access to the cat’s methods. The constructorAnimal()
is called again. - Lines 11-12: Now
talk()
makes the animal meow, whilerun()
is the same as when theanimal
was aDog
. - Line 14: Whenever the constructor
Animal()
was called, the counter was increased by one. So, since we have created 2 animals, the counter reflects that.
6. Conclusion
By now, you should be able to create an abstract class in Java and use it effectively. You can find the source code on our GitHub page.