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
.
// 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.
// 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.
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.
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
andInteger
arefinal
.
// 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 callsmyObject.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 likeHashMap
andHashSet
.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.