Java Public, Protected, Default, Private Keywords

Access modifiers in Java are keywords that control the visibility and accessibility of classes, interfaces, variables, methods, and constructors. They are crucial for implementing encapsulation, a core principle of object-oriented programming, which involves bundling data and the methods that operate on that data, and restricting direct access to some of the object’s components. Java provides four access modifiers:  

  1. public: The most permissive access level. Members declared as public are accessible from any other class, regardless of whether they are in the same package or a different package.   

  2. protected: Provides access to members within the same package and also to subclasses (even if they are in a different package).  

  3. default (no modifier): Also known as package-private. Members with no access modifier are accessible only within the same package. They are not accessible from classes in other packages.   

  4. private: The most restrictive access level. Members declared as private are only accessible within the same class. They are not accessible from any other class, not even subclasses.   

 

Summary Table:

Access Modifier Same Class Same Package Subclass (Different Package) Other Package
public Yes Yes Yes Yes
protected Yes Yes Yes No
default (no modifier) Yes Yes No No
private Yes No No No

Detailed Explanation with Examples:

Let’s illustrate the access modifiers with a practical example:

package com.example.access; // Package declaration

class MyClass {
    public int publicVar = 10;
    protected int protectedVar = 20;
    int defaultVar = 30; // No access modifier (default/package-private)
    private int privateVar = 40;

    public void publicMethod() {
        System.out.println("Public method");
        System.out.println(privateVar); // Accessing private within the same class is allowed
    }

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

    void defaultMethod() {
        System.out.println("Default method");
    }

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

class AnotherClass {  // In the same package (com.example.access)
    public static void main(String[] args) {
        MyClass obj = new MyClass();
        System.out.println(obj.publicVar); // Accessing public is allowed
        System.out.println(obj.protectedVar); // Accessing protected within the same package is allowed
        System.out.println(obj.defaultVar); // Accessing default within the same package is allowed
        // System.out.println(obj.privateVar); // Compile-time error: private is not accessible
        obj.publicMethod();
        obj.protectedMethod();
        obj.defaultMethod();
        // obj.privateMethod(); // Compile-time error: private is not accessible
    }
}


package com.example.anotherpackage; // Different package

import com.example.access.MyClass;

class DifferentPackageClass extends MyClass { //Subclass in different package
    public static void main(String[] args) {
        MyClass obj = new MyClass();
        System.out.println(obj.publicVar); // Accessing public is allowed
        // System.out.println(obj.protectedVar); // Compile-time error: protected is not accessible from another package without inheritance
        // System.out.println(obj.defaultVar); // Compile-time error: default is not accessible from another package
        // System.out.println(obj.privateVar); // Compile-time error: private is not accessible

        DifferentPackageClass obj2 = new DifferentPackageClass();
        System.out.println(obj2.publicVar); // Accessing public is allowed
        System.out.println(obj2.protectedVar); // Accessing protected is allowed as it is a subclass
        // System.out.println(obj2.defaultVar); // Compile-time error: default is not accessible from another package
        // System.out.println(obj2.privateVar); // Compile-time error: private is not accessible

        obj.publicMethod();
        // obj.protectedMethod(); // Compile-time error: protected is not accessible from another package without inheritance
        // obj.defaultMethod(); // Compile-time error: default is not accessible from another package
        // obj.privateMethod(); // Compile-time error: private is not accessible

        obj2.publicMethod();
        obj2.protectedMethod(); // Accessing protected is allowed as it is a subclass
        // obj2.defaultMethod(); // Compile-time error: default is not accessible from another package
        // obj2.privateMethod(); // Compile-time error: private is not accessible
    }
}

Java Public, Protected, Default, Private Keywords

When to Use Which Access Modifier:

  • public: Use for members that need to be accessible from anywhere. Typically used for the main interface of your classes.  

  • protected: Use when you want members to be accessible to subclasses, even if they are in a different package, and also within the same package. Useful for inheritance scenarios.   

  • default (no modifier): Use when you want members to be accessible only within the same package. Provides a level of encapsulation within a package.

  • private: Use for members that should only be accessible within the same class. This is the primary way to achieve data hiding and encapsulation.  

Best Practices:

  • Minimize access: Start with the most restrictive access level (private) and only widen it if necessary. This promotes better encapsulation and reduces the risk of unintended side effects.   

  • Use private for instance variables: Instance variables (data members) should almost always be private. Access to them should be controlled through public “getter” and “setter” methods (also known as accessor and mutator methods). This allows you to validate data and control how it’s modified.

  • Consider protected for inheritance: If you’re designing classes for inheritance, protected is often the appropriate access level for members that subclasses need to access but should not be part of the public interface of the class.

Related Posts