Chapter[10]: Hierarchy of Packages, Classes, Access Modifiers, and Subclasses in Java

Automate This. By Mrigank Saxena
6 min readDec 19, 2024

--

Another important aspect of learning Java is understanding the hierarchy and use of basic modifiers, classes, and subclasses. Grasping the structure of packages, classes, access modifiers, and inheritance is essential for writing well-organized code. Here’s a simple breakdown of these concepts using examples with Car objects.(Promise will move to another example soon)

1. Package: The Organizational Folder

What is a Package?

A package is a namespace for organizing classes and interfaces(will discuss later with examples). It groups related classes together to avoid name conflicts and makes your code modular.

Example:

package vehicles; // Declares that this class "Car" belongs to the "vehicles" package

public class Car {
public String make;
public String model;
public Car(String make, String model) {
this.make = make;
this.model = model;
}
}

Hierarchy:

  • Packages are at the top level.
  • Classes belong to packages, much like files belong to folders.

2. Class: The Blueprint of Objects

What is a Class?

A class is the blueprint for creating objects. It encapsulates fields (data) and methods (behavior).

Example:

package vehicles;  // Package

public class Car { // Class definition
public String make;
public String model;

public Car(String make, String model) { // Constructor
this.make = make;
this.model = model;
}
}
  • The Car class defines attributes (make, model) and a constructor to initialize them.
  • You can create multiple objects (like myCar, yourCar) from this class.

3. Subclass: The Specialized Class

What is a Subclass?

A subclass(also known as child class) is a class that inherits from another class(called the superclass: also known as parent class or base class, We will learn more about this in the next chapter), It extends the functionality of the superclass and can add its own fields and methods.

Example:

package vehicles; //here package is same but the class is diffrent 

public class SportsCar extends Car { // The SportsCar class is a subclass of Car. The 'extends' keyword is used to make the Car class the superclass in the same package. By extending Car, SportsCar becomes the subclass.
private int topSpeed;
public SportsCar(String make, String model, int topSpeed) {
super(make, model); // Calls the constructor of the superclass (Car) from sub class
this.topSpeed = topSpeed;
}

public void displayDetails() {
System.out.println("Make: " + make); // Inherited from Car
System.out.println("Model: " + model); // Inherited from Car
System.out.println("Top Speed: " + topSpeed + " mph"); // Subclass-specific
}
}

Hierarchy:

  • Subclasses inherit the properties and methods of the superclass.
  • Subclasses can override methods or add their own unique fields and behaviors.

4. Access Modifiers: Controlling Visibility

What are Access Modifiers?

Access modifiers determine who can access fields, methods, or classes. In Java, the main modifiers are(A Package may have many classes ):

Modifier Access Level:

public: Accessible from anywhere.

protected: Accessible within the same package and by subclasses(for example from supercar class ).

default: Accessible only within the same package.

private: Accessible only within the defining class.

Example: Access Modifiers in Action

File: Car.java

package vehicles;

public class Car {
public String make; // Public: Accessible anywhere
protected String model; // Protected: Accessible within package and subclasses "sportsCar"
private int year; // Private: Accessible only in this class "Car"
public Car(String make, String model, int year) {
this.make = make;
this.model = model;
this.year = year;
}
public int getYear() { // Public method to access private field
return year;
}
}

File: TestCar.java (Same Package)

package vehicles;

public class TestCar {
public static void main(String[] args) {
Car myCar = new Car("Toyota", "Camry", 2023);
System.out.println("Make: " + myCar.make); // Public: Accessible
System.out.println("Model: " + myCar.model); // Protected: Accessible within the same package
System.out.println("Year: " + myCar.getYear()); // Access private field via public method
}
}

File: LuxuryCar.java (Subclass in Different Package)

package premium;

import vehicles.Car;
public class LuxuryCar extends Car { // Subclass of Car
private String feature;
public LuxuryCar(String make, String model, int year, String feature) {
super(make, model, year); // Calls the Car constructor
this.feature = feature;
}
public void displayDetails() {
System.out.println("Make: " + make); // Public: Accessible
System.out.println("Model: " + model); // Protected: Accessible in subclass
// System.out.println("Year: " + year); // Private: Not accessible, causes error
System.out.println("Feature: " + feature);
}
}

Hierarchy of Access Modifiers in Subclasses

  1. Public (public): Accessible everywhere, including subclasses in different packages.
  2. Protected (protected): Accessible within the same package or by subclasses, even in different packages.
  3. Default (No Modifier): Accessible only within the same package.
  4. Private (private): Accessible only within the class where it is defined.

5. Combined Example: Packages, Classes, Subclasses, and Modifiers

File: Car.java

package vehicles;

public class Car {
public String make; // Accessible anywhere
protected String model; // Accessible within package and subclasses
private String color; // Accessible only in this class
public Car(String make, String model, String color) {
this.make = make;
this.model = model;
this.color = color;
}
public String getColor() { // Public method to access private field
return color;
}
}

File: TestCar.java (Same Package)

package vehicles;

public class TestCar {
public static void main(String[] args) {
Car myCar = new Car("Honda", "Civic", "Red");
System.out.println("Make: " + myCar.make); // Public: Accessible
System.out.println("Model: " + myCar.model); // Protected: Accessible
System.out.println("Color: " + myCar.getColor());// Access private field via public method
}
}

File: SportsCar.java (Different Package)

package sports;

import vehicles.Car;
public class SportsCar extends Car {
private int topSpeed;
public SportsCar(String make, String model, String color, int topSpeed) {
super(make, model, color); // Calls the Car constructor
this.topSpeed = topSpeed;
}
public void displayDetails() {
System.out.println("Make: " + make); // Public: Accessible
System.out.println("Model: " + model); // Protected: Accessible in subclass
// System.out.println("Color: " + color); // Private: Not accessible
System.out.println("Top Speed: " + topSpeed + " mph");
}
}

Key Takeaways

Feature Descriptions with Examples

1. Package

  • Purpose: Organizes related classes into groups for better code management.
  • Example:
package vehicles;
  • Declares the package vehicles, grouping classes like Car and SportsCar into one package.

2. Class

  • Purpose: A blueprint to define objects and their behaviors (attributes and methods).
  • Example:
public class Car {     // Fields and methods 
}
  • Defines a class Car with fields (like make, model) and methods.

3. Subclass

  • Purpose: Extends functionality from a superclass (inheritance).
  • Example:
public class SportsCar extends Car {     // Additional features 
}
  • SportsCar inherits fields and methods from Car and can add new functionality.

4. Access Modifiers

Access modifiers control the visibility of classes, fields, and methods.

a. Public (public)

  • Purpose: Accessible from anywhere.
  • Example:
public String make;
  • A public field or method can be accessed from any class.

b. Protected (protected)

  • Purpose: Accessible within the same package and by subclasses in other packages.
  • Example:
protected String model;
  • A protected field is not accessible to unrelated classes outside the package.

c. Default (no modifier)

  • Purpose: Accessible only within the same package (package-private).
  • Example:
String color;
  • A field without an explicit modifier is default-accessible.

d. Private (private)

  • Purpose: Accessible only within the defining class.
  • Example:
private String color;
  • A private field cannot be accessed outside its class, ensuring strict encapsulation.

Example Code Combining All Features:

package vehicles; // Package declaration

// Class definition
public class Car {
public String make; // Public: accessible anywhere
protected String model; // Protected: accessible within package or subclass
String color; // Default: accessible within the same package
private String engineType; // Private: accessible only in this class
public Car(String make, String model, String color, String engineType) {
this.make = make;
this.model = model;
this.color = color;
this.engineType = engineType;
}
}
// Subclass example
public class SportsCar extends Car {
public SportsCar(String make, String model, String color, String engineType) {
super(make, model, color, engineType);
}
public void showDetails() {
System.out.println("Make: " + make); // Accessible (public)
System.out.println("Model: " + model); // Accessible (protected)
System.out.println("Color: " + color); // Accessible (default, same package)
// System.out.println("Engine: " + engineType); // Error: Private field
}
}

Key Takeaways:

  1. Use public for maximum accessibility.
  2. Use protected to allow subclass access but limit exposure to unrelated classes.
  3. Use default for package-private access when the class won’t be used outside the package.
  4. Use private to encapsulate and protect sensitive data.

By leveraging packages, classes, access modifiers, and subclasses, you can build scalable and modular Java programs with clear boundaries for accessibility and functionality!

Happy Coding!

--

--

Automate This. By Mrigank Saxena
Automate This. By Mrigank Saxena

Written by Automate This. By Mrigank Saxena

Join me as I share insights, tips, and experiences from my journey in quality assurance, automation, and coding! https://www.linkedin.com/in/iammriganksaxena/

Responses (2)