Skip to content

Abstract class

An abstract class in Java is a restricted class that cannot be used to create objects (it cannot be instantiated). Its purpose is to serve as a blueprint for other classes. An abstract class can have both abstract methods (methods without a body) and regular, concrete methods.

Any class that contains one or more abstract methods must also be declared abstract. abstract keyword is used to declare both abstract classes and abstract methods.

  • Abstract Class: abstract class ClassName { ... }

  • Abstract Method: abstract returnType methodName(parameters); (Note the semicolon instead of curly braces {}).

The primary use of abstract classes is to achieve abstraction. They allow to define a common interface for a group of related subclasses, forcing each subclass to provide its own implementation for the abstract methods while also allowing them to share common functionality from the superclass's concrete methods.

abstract class is used to create a template for a group of subclasses where the abstract methods will have different implementations in each one.

For example, a Shape class might have an abstract calculateArea() method because the formula for area is different for a Circle versus a Rectangle.

java
// Abstract superclass
abstract class Animal {
    // Abstract method (does not have a body)
    public abstract void makeSound();

    // Regular method
    public void sleep() {
        System.out.println("Zzz...");
    }
}

// Concrete subclass
class Dog extends Animal {
    // Provides the body for the abstract method from Animal
    public void makeSound() {
        System.out.println("Woof!");
    }
}

public class AbstractDemo {
    public static void main(String[] args) {
        // Animal myAnimal = new Animal(); 
        // This would cause a compile error.
        
        Dog myDog = new Dog();
        myDog.makeSound(); // Calls the method in the Dog class
        myDog.sleep();     // Calls the method in the Animal class
    }
}

Shape Class

abstract Shape class with an abstract area() method. Two concrete subclasses, Rectangle and Triangle, extend Shape and provide their own specific implementations for calculating the area.

java
// The abstract class 'Shape'
abstract class Shape {
    double dim1;
    double dim2;

    Shape(double a, double b) {
        dim1 = a;
        dim2 = b;
    }

    abstract double area();
}

// Concrete subclass 'Rectangle'
class Rectangle extends Shape {
    Rectangle(double width, double height) {
        super(width, height); 
    }

    // implementation for the abstract method
    @Override
-    double area() {
        System.out.println("Calculating area for a rectangle...");
        return dim1 * dim2;
    }
}

// Concrete subclass 'Triangle'
class Triangle extends Shape {
    Triangle(double base, double height) {
        super(base, height);
    }

    @Override
    double area() {
        System.out.println("Calculating area for a triangle...");
        return (dim1 * dim2) / 2;
    }
}

// Demo class to test the Shape implementations
public class ShapeAreaDemo {
    public static void main(String[] args) {
        // Can have a reference of abstract type.
        Shape shapeRef;

        Rectangle r = new Rectangle(10, 5);
        Triangle t = new Triangle(10, 8);

        // Point shapeRef to a Rectangle object
        shapeRef = r;
        System.out.println("Area is: " 
	        + shapeRef.area());

        // Point shapeRef to a Triangle object
        shapeRef = t;
        System.out.println("Area is: " 
	        + shapeRef.area());
    }
}

Output:

Calculating area for a rectangle...
Area is: 50.0
Calculating area for a triangle...
Area is: 40.0

final

The final keyword in Java is a modifier used to apply a restriction on a class, method, or variable. Essentially, it makes an entity unchangeable. The specific meaning depends on what it's applied to.

1. final Variables (Constants)

When the final keyword is used with a variable, its value cannot be modified after it has been assigned. It effectively creates a constant.

  • Purpose: To create constants whose values remain the same throughout the program, like the value of Pi or a configuration setting.
java
class Circle {
	// A final variable - a constant.
	final double PI = 3.14159;
	double radius;

	public Circle(double r) {
		this.radius = r;
		// PI = 3.14; 
		// This would cause a compile error.
	}

	public double getArea() {
		return PI * radius * radius;
	}
}

2. final Methods (Cannot be Overridden)

When a method is declared as final, it cannot be overridden by any subclass.

  • Purpose: To prevent subclasses from altering the core implementation of a crucial method, ensuring its behavior remains consistent across the entire class hierarchy.
java
class Vehicle {
	// This method cannot be changed by any subclass.
	public final void displayLicensePlate() {
		System.out.println("Displaying standard license plate.");
	}
}

class Car extends Vehicle {
	@Override
	public void displayLicensePlate() { 
	     System.out.println("Custom display.");
	 } 	// This would cause a compile error:
}

3. final Classes (Cannot be Extended)

When a class is declared as final, it cannot be subclassed (or inherited from).

  • Purpose: To create immutable classes or to prevent extension for security reasons. For example, standard classes like String and Integer are final.
java
// This class cannot be extended by any other class.
final class SecureData {
	private String data;
	// ... methods
}

// This would cause a compile error:
class HackedData extends SecureData {
	// Cannot inherit from a final class.
 }

The java.lang.Object Class

The java.lang.Object class is the ultimate root of the class hierarchy in Java. Every single class, whether you define it or it comes from the Java library, is a descendant of the Object class. If a class definition does not explicitly use the extends keyword, it implicitly inherits from Object.

Significance

The significance of Object is that it provides a set of fundamental methods that are available to every object in Java. This guarantees that every object has a baseline of common functionality.

Key methods provided by Object include:

  • toString(): Returns a string representation of the object. By default, it returns the class name and memory address, but it's often overridden to provide a more meaningful description (e.g., System.out.println(myObject) implicitly calls myObject.toString()).

  • equals(Object obj): Compares two objects for equality. The default implementation checks if two references point to the same memory location, but it's often overridden to compare the actual contents of the objects.

  • hashCode(): Returns a hash code (an integer) for the object, which is primarily used by hash-based collections like HashMap and HashSet.

  • getClass(): Returns the runtime class of the object.

Because every class inherits from Object, you can have a variable of type Object refer to an instance of any other class, which is fundamental to polymorphism and many generic algorithms.

Made with ❤️ for students, by a fellow learner.