Java Modifiers

Java Modifiers: Access and Behavior Contro

Modifiers in Java are keywords that define the accessibility, behavior, and properties of classes, methods, and variables. Java modifiers can be broadly categorized into access modifiers and non-access modifiers. Access modifiers define the visibility of classes, methods, and variables, while non-access modifiers provide additional properties like immutability, synchronization, or the ability to override behaviors.

Understanding Java modifiers is crucial, as they help you encapsulate data, control access, and add specific functionalities to your code.

Types of Modifiers in Java

Modifiers in Java are divided into two main categories:

  1. Access Modifiers
  • Control the visibility of classes, methods, and variables.
  • Types: public, protected, default (no keyword), private.
  1. Non-Access Modifiers
  • Control specific properties or behavior.
  • Types: static, final, abstract, synchronized, transient, volatile.

Let’s explore each type in detail.


1. Access Modifiers

Access modifiers determine the visibility of a class, method, or variable. There are four access modifiers in Java:

ModifierClassPackageSubclassWorld
publicYesYesYesYes
protectedYesYesYesNo
(default)YesYesNoNo
privateYesNoNoNo

public Access Modifier

  • Class-Level: The class is accessible from any other class in the program.
  • Method/Variable-Level: The variable or method can be accessed from any class.

Example of public Modifier:

public class Car {
    public String brand;

    public void displayBrand() {
        System.out.println("Brand: " + brand);
    }
}

private Access Modifier

  • Class-Level: Not allowed on top-level classes.
  • Method/Variable-Level: The variable or method can only be accessed within the class it is declared in.

Example of private Modifier:

public class Car {
    private String engineNumber;

    private void showEngineNumber() {
        System.out.println("Engine Number: " + engineNumber);
    }
}

protected Access Modifier

  • Class-Level: Not allowed on top-level classes.
  • Method/Variable-Level: The variable or method can be accessed within the same package or by subclasses.

Example of protected Modifier:

public class Vehicle {
    protected String model;

    protected void displayModel() {
        System.out.println("Model: " + model);
    }
}

Default (Package-Private) Access Modifier

  • If no access modifier is specified, the class, method, or variable is only accessible within the same package.

Example of Default Access Modifier:

class Bike {
    String color; // package-private access

    void displayColor() {
        System.out.println("Color: " + color);
    }
}

2. Non-Access Modifiers

Non-access modifiers control additional properties and behaviors.

static Modifier

  • Method/Variable-Level: Belongs to the class rather than to any specific instance.
  • Usage: To define class-level variables and methods.

Example of static Modifier:

public class Car {
    public static int totalCars = 0;

    public static void displayTotalCars() {
        System.out.println("Total Cars: " + totalCars);
    }
}

final Modifier

  • Class-Level: Prevents the class from being subclassed.
  • Method-Level: Prevents the method from being overridden.
  • Variable-Level: Prevents the variable from being changed after it’s initialized (makes it a constant).

Example of final Modifier:

public final class Car {
    public final int maxSpeed = 200;

    public final void showMaxSpeed() {
        System.out.println("Max Speed: " + maxSpeed);
    }
}

abstract Modifier

  • Class-Level: Defines an abstract class that cannot be instantiated.
  • Method-Level: Defines an abstract method that must be implemented in subclasses.

Example of abstract Modifier:

public abstract class Vehicle {
    public abstract void drive(); // No implementation here
}

public class Car extends Vehicle {
    public void drive() {
        System.out.println("Driving the car.");
    }
}

synchronized Modifier

  • Method/Block-Level: Ensures that only one thread can execute the method or block at a time.

Example of synchronized Modifier:

public class BankAccount {
    private double balance;

    public synchronized void deposit(double amount) {
        balance += amount;
    }
}

transient Modifier

  • Variable-Level: Prevents the serialization of certain variables, so they are not included in serialized objects.

Example of transient Modifier:

public class User {
    public String username;
    public transient String password; // Will not be serialized
}

volatile Modifier

  • Variable-Level: Indicates that a variable’s value may change asynchronously, ensuring that all threads see the latest value.

Example of volatile Modifier:

public class SharedResource {
    public volatile boolean isActive;
}

Exercises

Let’s practice using modifiers through the following exercises.


Exercise 1: Access Modifiers in a BankAccount Class

  1. Create a BankAccount class with attributes accountNumber (String) and balance (double).
  2. Use private for both attributes.
  3. Add a public method deposit(double amount) to add to the balance and public method withdraw(double amount) to subtract from the balance if funds are sufficient.
  4. Add a public method getBalance() to return the current balance.
  5. Create a BankAccount object and test the methods.

Expected Outcome: You should only be able to access the deposit, withdraw, and getBalance methods, not the accountNumber and balance directly.


Exercise 2: Using static Modifier in a Library Class

  1. Create a Library class with:
  • A static variable totalBooks (int) to keep track of the total number of books.
  • An instance variable bookTitle (String) to hold the book’s title.
  1. Create a constructor that increments totalBooks by 1 each time a new book is added.
  2. Add a static method displayTotalBooks() to display the total number of books.
  3. Create multiple Library objects and call displayTotalBooks().

Expected Outcome: The total book count should increase each time a new book is created, and displayTotalBooks() should reflect the correct total.


Exercise 3: Working with final Modifier in a Vehicle Class

  1. Create a Vehicle class with:
  • A final variable MAX_SPEED (int) set to 120.
  • A final method showMaxSpeed() that displays MAX_SPEED.
  1. Create a subclass Car that inherits from Vehicle.
  2. Try to override showMaxSpeed() in Car and observe the error.
  3. In Vehicle, add a public method drive() and override it in Car.

Expected Outcome: You should see that MAX_SPEED and showMaxSpeed() cannot be modified or overridden.


Exercise 4: Creating Abstract Class for Shapes

  1. Create an abstract class Shape with an abstract method calculateArea().
  2. Create subclasses Circle and Rectangle that implement calculateArea().
  3. In Circle, accept a radius, and in Rectangle, accept length and width.
  4. Test the area calculation for each shape by creating objects of Circle and Rectangle.

Expected Outcome: Each subclass should correctly implement calculateArea(), demonstrating the use of abstract classes.


Exercise 5: Using transient Modifier in User Class

  1. Create a User class with:
  • A String attribute username.
  • A transient String attribute password.
  1. Serialize and deserialize a User object and observe that the password field is not preserved.

Expected Outcome: The password field should be null after deserialization, demonstrating the effect of the transient modifier.


Exercise 6: Volatile and Synchronized Modifiers for Multi-threading

  1. Create a Counter class with:
  • A volatile boolean attribute active set to true.
  • A synchronized method increment() that increases a count by 1 while active is true.
  1. Start a thread that increments the count.
  2. Create a second thread to change active to false after a delay.

Expected Outcome: The count should stop increasing when active is set to false, showing the effect of volatile and synchronized.


Conclusion

Modifiers in Java offer powerful ways to control access, behavior, and properties of classes, methods, and variables. Access modifiers (public, private, protected, default) control visibility, while non-access modifiers (static, final, abstract, synchronized, transient, volatile) manage various properties like immutability, inheritance control, and thread safety. Through exercises, you can gain a strong grasp of using modifiers effectively to improve code structure, security, and efficiency.

Happy coding!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top