Mastering Interfaces and Class Inheritance in Java

Java Interfaces

An interface in Java is a reference type that serves as a blueprint for classes. It can contain constants, method signatures, default methods, static methods, and private methods. Interfaces cannot be instantiated directly but are implemented by classes or extended by other interfaces.

Defining and Implementing an Interface

Interfaces are declared using the interface keyword. By default, all members of an interface are public. Abstract methods within an interface are implicitly public abstract, and variables are implicitly public static final.

public interface Connectable {
    // Implicitly public static final
    String PROTOCOL = "HTTPS";

    // Abstract method
    void connect();

    // Default method (Java 8+)
    default void logStatus() {
        System.out.println("Current protocol: " + PROTOCOL);
    }

    // Static method (Java 8+)
    static boolean isAvailable(String service) {
        return service != null && !service.isEmpty();
    }
}

A class implements an interface using the implements keyword. If a class implements an interface, it must provide concrete implementations for all its abstract methods unless the class itself is abstract.

public class WebServer implements Connectable {
    private String serverName;

    public WebServer(String name) {
        this.serverName = name;
    }

    @Override
    public void connect() {
        System.out.println(serverName + " is connecting via " + PROTOCOL);
    }
}

Class Inheritance

Inheritance allows a subclass to inherit fields and methods from a superclass. In Java, a class can only extend one superclass (single inheritance), but it can implement multiple interfaces. All Java classes implicitly inherit from the java.lang.Object class.

The super Keyword

The super keyword is used to refer to the immediate superclass. It is commonly used to call the superclass constructor or to access overridden methods.

public class Device {
    protected String brand;

    public Device(String brand) {
        this.brand = brand;
    }

    public void powerOn() {
        System.out.println("Device powering on...");
    }
}

public class Smartphone extends Device {
    private double batteryLevel;

    public Smartphone(String brand, double battery) {
        // Calls the superclass constructor
        super(brand);
        this.batteryLevel = battery;
    }

    @Override
    public void powerOn() {
        super.powerOn(); // Calls the parent method
        System.out.println(brand + " smartphone at " + batteryLevel + "% battery.");
    }
}

Polymorphism and Type Casting

Polymorphism allows an object to take multiple forms. A subclass object can be referenced by a variable of its superclass type or any interface it implements. This is known as upcasting.

Device myPhone = new Smartphone("Apple", 85.0); 
myPhone.powerOn(); // Executes the overridden method in Smartphone

Downcasting is the process of casting a superclass reference back to a subclass type. This requires an explicit cast and should be checked using the instanceof operator to avoid a ClassCastException.

if (myPhone instanceof Smartphone) {
    Smartphone sp = (Smartphone) myPhone;
    System.out.println("Accessed subclass specific behavior.");
}

Abstract Classes vs. Interfaces

While both provide abstraction, they serve different purposes:

  • Abstract Classes: Used when classes share a common identity and state. They can have non-static fields and non-public constructors.
  • Interfaces: Used to define a common contract or capability across unrelated classes. They focus on "what an object can do" rather than "what it is."
public abstract class AbstractSensor {
    private int id;

    public AbstractSensor(int id) {
        this.id = id;
    }

    public abstract double readData();

    public void displayId() {
        System.out.println("Sensor ID: " + id);
    }
}

Anonymous Inner Classes

Anonymous classes allow you to declare and instantiate a class at the same time. They are useful for one-time implementations of interfaces or abstract classes without creating a formal named class.

Connectable tempConnection = new Connectable() {
    @Override
    public void connect() {
        System.out.println("Temporary connection established.");
    }
};
tempConnection.connect();

Java Initialization Sequence

Understanding the order in which blocks of code are executed is critical for debugging complex inheritance hierarchies. The order is generally as follows:

  1. Static Members: Static variables and static blocks are initialized when the class is first loaded, starting from the base class down to the most derived class.
  2. Instance Members: When an object is created, instance variables and instance initialization blocks of the superclass are processed.
  3. Constructors: The superclass constructor is executed before the subclass constructor.
public class Base {
    static { System.out.println("Base: Static Block"); }
    { System.out.println("Base: Instance Block"); }
    public Base() { System.out.println("Base: Constructor"); }
}

public class Derived extends Base {
    static { System.out.println("Derived: Static Block"); }
    { System.out.println("Derived: Instance Block"); }
    public Derived() { System.out.println("Derived: Constructor"); }

    public static void main(String[] args) {
        new Derived();
    }
}
// Output:
// Base: Static Block
// Derived: Static Block
// Base: Instance Block
// Base: Constructor
// Derived: Instance Block
// Derived: Constructor

Final Methods and Classes

The final keyword provides restrictions on inheritance:

  • A final class cannot be extended.
  • A final method cannot be overridden by subclasses.

Tags: java OOP Inheritance interfaces Polymorphism

Posted on Sat, 24 Oct 2026 16:07:58 +0000 by MBK