Access Modifiers

You have already used access modifiers; public, private etc., class definitions, methods and variables, and now you will understand these in detail.

As the name suggests, these keywords when used before a class, method, variables, constructor will restrict the access from other classes, packages etc.. There are four types of access modifiers available in java:

  • private -- top level class cannot have private but any other member can have this modifier. Members with this modifier are totally restricted to other members of the given class only and not to any other class including its children.
  • default (no modifier used, a.k.a package access) -- members with no modifiers can be accessed by other classes but from the same package
  • protected -- members with this modifiers can be accessed by the classes in the same package and also by its children
  • public -- members of this type have no restrictions of anytype and so can be accessed by any class in any package.

Let us understand these concepts in detail

private

private modifier is the most restrictive of all the accessibility modifiers. private modifier is heavily used for declaring variables and methods. While private modifier cannot be used for a top level class, it can used for defining nested classes.

As the name suggests, anything declared private is only accessible by the class in which it is declared. Not even a sub class of that class can access a private member variable.

private variables

When you declare a variable private, the variable can be initialized or modified by only statements present in the same class. When you follow the principles of encapsulation, you declare all variables private. And the variables are given individual methods which will have public accessibility and hence can be used by other classes to set or modify the variable values.

Here is an example:

class Student {

    private String name;

    public String getFirstName() {
        return this.name;
    }

    public void setFirstName(String name) {
        this.name= name;
    }
}

public class School {

    public static void main(String[] args) {
        Student student = new Student();
        student.setFirstName("John");
    }
}

In the above example you see two classes; Student and School. Student class has a private variable firstName which is given a public accessor methods for setting and getting its values. In the School class's main method, Student object is instantiated and its name is set through the public access methods.

In the above example, if you remove the private modifier for the variable, then you can directly set the variable value in the main method instead of using its access methods.

class Student {

    String name;

    public String getFirstName() {
        return this.name;
    }

    public void setFirstName(String name) {
        this.name= name;
    }
}

public class School {

    public static void main(String[] args) {
        Student student = new Student();
        student.name("John");
    }
}

The above way of directly setting the value of the variable is not considered a good practice. The reason being, a program may set an invalid value to the variable and there is nothing you can do about it. For example, suppose the user sets his/her name with numbers for name, then it is not valid value for first name of any person. when you encounter an invalid value, you would like to tell the user to input the correct value. You can do so if you were setting the value through setter method. Here is the revised example with validation:

class School {

    public static void main(String[] args) {
        Student student = new Student();
        student.setFirstName("123");
    }
}

class Student {

    private String name;

    public String getFirstName() {
        return this.name;
    }

    public void setFirstName(String name) {

        try {  
            double d = Double.parseDouble(name); 
            throw new IllegalArgumentException("firstname cannot be numeric");
          }  catch(NumberFormatException nfe)  {  
            this.name= name;
            System.out.println("firstname is valid");
          }  
    }
}

Notice that in the above code, if the given input is a valid string, then it falls into the exception block and then you set the name variable to the value that is given. If the given input is a numeric then you create and throw IllegalArgumentException.

Exercise: Change the value of name from '123' to some alpha character and see the output.

private methods

Just like private variables, private methods cannot be accessed by other classes including its own children. The method can be accessed only by other members of its own class.

class ChildClass extends SuperClass {

    public static void main(String[] args) {
        ChildClass childClass = new ChildClass();
        childClass.displayTimeinMillis();
    }
}

class SuperClass {

    private void displayTimeinMillis() {
        System.out.println(System.currentTimeMillis());
    }

    private void anotherMethod() {
        this.displayTimeinMillis();
    }
}

You will get compilation error when you try to write the above code. Now remove the private keyword on the displayTimeInMillis method and see it work!

In a similar way you can declare a private nested class, in which case, the nested class can be accessed by members of the same class and not any other class. From now on member of a class means the non static variables, methods and even the nested classes declared within the class.

default - package

When no modifier is specified, then the members get default accessibility (a.k.a package access). In this case all the variables or methods which have default accessibility can be accessed by other classes from the same package and not by classes which belong to other packages.

package com.mbcc.b;
import com.mbcc.a.SuperClass;

public class ChildClass extends SuperClass {

    public static void main(String[] args) {
        ChildClass childClass = new ChildClass();
        childClass.displayTimeinMillis();

        SuperClass superClass = new SuperClass();
        superClass.displayTimeinMillis();
    }
}

package com.mbcc.a;
class SuperClass {

     protected void displayTimeinMillis() {
        System.out.println(System.currentTimeMillis());
    }

}

package com.mbcc.a;

public class AnotherClass {

    public static void main(String[] args) {
        SuperClass superClass = new SuperClass();
        superClass.displayTimeinMillis();
    }

}

To see this working, create two packages 'com.mbcc.a' and 'com.mbcc.b' and create SuperClass, ChildClass, AnotherClass as shown in the code. You will see compilation errors in ChildClass when you try to access displayTimeinMillis method from either the ChildClas or the Superclass.

protected

When you declare a member protected in any class, then all classes in the package containing the class and all the subclasses of the class in any package can access the protected member.

To see this working, change the modifier to protected for displayTimeinMillis method in SuperClass in the above program. You will now see that ChildClass can access displayTimeinMillis method of the Superclass. However the SuperClass which is instantiated in the ChildClass is still unable to access this method. This is really interesting to note that the even though you are instantiating the SuperClass in the ChildClass, since you are directly accessing the protected member of the SuperClass's method in the ChildClass, it is not visible.

public

When you declare a member public then there is no restricted of any sort for any of the classes. Any class from any package, whether it is a subclass or not will be able to access public accessors. If you now change the accessor of displayTimeinMillis to public then all the compilation errors vanish.

results matching ""

    No results matching ""