An abstract class is a class you can’t create an object of — you add the abstract keyword when
declaring it. Normally the classes we create are concrete classes.
An abstract class can have an abstract method. An abstract method also begins with the abstract
keyword and has no body. A method without a body is (almost always) part of an abstract class,
and a class with an abstract method is automatically abstract. Since the abstract method isn’t
completely defined (it lacks a body), the class itself isn’t fully defined either — so you can’t
create objects of it.
abstract class Super { Super() { System.out.println("Super"); } void method1() { System.out.println("Super Method"); } abstract void method2();}
class Sub extends Super { void method2() { System.out.println("Sub Method 2"); }}Even though Sub inherits from Super, Sub is not an abstract class — it’s concrete. This is
because Sub inherited the constructor, method1, and method2 from Super, but overrides
method2, so everything in Sub is now fully defined.
If a class inherits from an abstract class, it also becomes abstract unless it overrides every method of the parent class — at which point it becomes concrete.
Why we need abstract classes
They’re meant for multiple inheritance and polymorphism — you write a subclass that inherits from the abstract superclass and overrides its methods. Abstract classes are used for defining and imposing standards.
Notes
- You cannot create an object of an abstract class, only a reference.
- You can create an object of a concrete class that inherits from the abstract class.
- If even one method in your child class doesn’t override the parent’s, the child class becomes abstract too.
- The
@Overrideannotation on a child class isn’t a strict requirement, but it’s good practice.
Worked example
abstract class Super { public Super() { System.out.println("Super Constructor"); } public void meth1() { System.out.println("Meth1 of Super"); } abstract public void meth2();}
class Sub extends Super { @Override public void meth2() { System.out.println("Meth2 of sub class"); }}
public class AbstractExample { public static void main(String[] args) { Super s = new Sub(); s.meth1(); s.meth2(); }}A slightly bigger example — an abstract Hospital class that imposes a standard set of
operations on any concrete hospital implementation:
abstract class Hospital { abstract void emergency(); abstract void appointment(); abstract void admit(); abstract void billing();}
class MyHospital extends Hospital { MyHospital() { } @Override void emergency() { } @Override void appointment() { } @Override void admit() { } @Override void billing() { }}Abstract class vs. interface, side by side
abstract class Test1 { abstract public void meth1(); abstract public void meth2();}
class Test2 extends Test1 { @Override public void meth1() { } @Override public void meth2() { }}
interface TestOne { void methOne(); void methTwo();}
class TestTwo implements TestOne { public void methOne() { }
public void methTwo() { }}
public class AbstractVsInterface { public static void main(String[] args) { Test1 t = new Test2(); TestOne tee = new TestTwo(); }}