The difference between public, protected, package-private and private in java

Posted on

In Java, access modifiers are used to set the visibility of classes, methods, and variables, controlling where they can be accessed from within the application. The four primary access modifiers are public, protected, package-private (default, no keyword), and private. Each modifier serves a different purpose and scope of accessibility. Public allows access from any other class, protected permits access within the same package and subclasses, package-private (default) allows access only within the same package, and private restricts access to the defining class itself. Understanding these modifiers is crucial for encapsulation and maintaining a clear and secure architecture in Java applications.

Public

Global Access: The public access modifier provides the broadest level of accessibility. Classes, methods, or variables declared as public can be accessed from any other class, regardless of the package.

public class PublicClass {
    public void publicMethod() {
        System.out.println("Public method");
    }
}

public class Test {
    public static void main(String[] args) {
        PublicClass obj = new PublicClass();
        obj.publicMethod();  // Accessible from any class
    }
}

Use Case: Use the public modifier for APIs or methods that need to be accessible from different parts of the application or by other applications.

Protected

Package and Subclass Access: The protected access modifier allows access within the same package and subclasses, even if they are in different packages. This is commonly used in inheritance to allow subclasses to access certain methods or variables of the parent class.

class ParentClass {
    protected void protectedMethod() {
        System.out.println("Protected method");
    }
}

class ChildClass extends ParentClass {
    public void callProtectedMethod() {
        protectedMethod();  // Accessible within subclass
    }
}

Use Case: Use protected when you want to expose methods or variables to subclasses but keep them hidden from other parts of the application.

Package-Private (Default)

Package-Only Access: When no access modifier is specified, the default access level, known as package-private or default, is applied. This restricts access to classes, methods, or variables to other classes within the same package.

class PackagePrivateClass {
    void packagePrivateMethod() {
        System.out.println("Package-private method");
    }
}

class Test {
    public static void main(String[] args) {
        PackagePrivateClass obj = new PackagePrivateClass();
        obj.packagePrivateMethod();  // Accessible within the same package
    }
}

Use Case: Use package-private when you want to limit the visibility to the same package, which can be useful for encapsulating package-specific functionality.

Private

Class-Only Access: The private access modifier is the most restrictive. It allows access only within the class where it is declared. This is typically used to hide implementation details and protect the internal state of an object.

public class PrivateClass {
    private void privateMethod() {
        System.out.println("Private method");
    }

    public void accessPrivateMethod() {
        privateMethod();  // Accessible within the same class
    }
}

public class Test {
    public static void main(String[] args) {
        PrivateClass obj = new PrivateClass();
        // obj.privateMethod();  // Not accessible, causes a compile-time error
        obj.accessPrivateMethod();  // Accessible through public method
    }
}

Use Case: Use private to encapsulate the internal workings of a class, ensuring that only methods within the same class can access these members.

Summary of Access Levels

Public: Accessible from any other class. Use for widely accessible API methods and classes.

Protected: Accessible within the same package and subclasses. Use for methods and variables intended to be used by subclasses.

Package-Private: Accessible only within the same package. Default access level if no modifier is specified. Use for package-specific functionality.

Private: Accessible only within the defining class. Use for internal implementation details and encapsulation.

Practical Examples

Class-Level Modifiers: A class itself can be declared as public or package-private (default). Top-level classes cannot be private or protected.

public class PublicClass {
    // Class-level public modifier
}

class PackagePrivateClass {
    // Class-level package-private modifier
}

Member-Level Modifiers: Fields and methods can be declared with any of the four access modifiers.

public class Example {
    public int publicField;
    protected int protectedField;
    int packagePrivateField;  // No modifier means package-private
    private int privateField;

    public void publicMethod() {}
    protected void protectedMethod() {}
    void packagePrivateMethod() {}  // No modifier means package-private
    private void privateMethod() {}
}

Best Practices

Encapsulation: Use private to encapsulate data and hide implementation details. This ensures that internal states are not exposed and can only be manipulated through public methods.

API Design: Use public for methods and classes that form the public API of your component or module, providing clear and stable entry points for users.

Inheritance: Use protected for methods and variables that are intended to be accessed or overridden by subclasses.

Package Design: Use package-private to restrict access to classes and methods within the same package, helping to group related functionality and encapsulate implementation details at the package level.

Understanding and using these access modifiers effectively allows for better encapsulation, improved modularity, and a more secure codebase.aa

Was this helpful?

Thanks for your feedback!