Access Specifiers in Java With Examples

What is Access Specifier?

The keywords that define the access scope is known as access specifier.

Till now, we have discussed the basic units of Java programming. We are aware of the encapsulation property, that links data with code. There is one more aspect of encapsulation i.e access control. Controlling access prevents misuse.

Let us take a real-life example. We all live together in our home, but not everyone has access to the money vault. Access by everyone might result in theft. So the key/code of the vault stays only with the guardian. We have controlled and limited the access of the vault to only the concerned ones.

Similarly, we can configure the accessibility of the class and its members i.e variables, methods, and constructor. This is possible due to access specifiers.

Types of access specifiers

There are usually four types of access specifiers:-

  • private
  • default
  • protected
  • public

Let us discuss each of them with a proper example.

private

The variable, method, and constructor defined as private will be accessible only inside the class. The purpose of the private variable and method is to restrict its usage only to the other members inside the class. Classes(except Nested Class) and Interfaces cannot be defined as private. Among all the modes, this is the most strict mode.

Example:

class MyAccess{
     //private variable
     private int myData=25;
}
public class ClassMain{
    public static void main(String args[])
    {
        MyAccess obj = new MyAccess();
        System.out.println("myData = "+obj.myData);
    }
}

Output:

ClassMain.java:16: error: myData has private access in MyAccess

        System.out.println("myData = "+obj.myData);

                                          ^

1 error

So we can see that myData cannot be accessed outside the class MyAccess.

Example 2:

class MyAccess{
     //private variable
     private int myData=25;

     //A private method that return myData
        private int getMyData(){
         System.out.println("I am inside the class, I can access myData");
         return myData;
     }
}



public class ClassMain{
    public static void main(String args[]){
        MyAccess obj = new MyAccess();
        System.out.println("myData = "+obj.getMyData());
    }
}

Output:

ClassMain.java:16: error: getMyData() has private access in MyAccess
System.out.println("myData = "+obj.getMyData());
                                          ^
1 error

Similarly, getMyData() cannot be accessed outside the class MyAccess.

In case, we want to restrict the object creation from outside the class, we declare constructors as private. This is used in various scenarios like singleton class.

Example:

class MyAccess{
    //private variable
     private int myData;

    //private constructor
     private MyAccess(int data){
        myData=data;
     }
}

public class ClassMain{
    public static void main(String args[]){
        MyAccess obj = new MyAccess(27);
    }
}

Output:

ClassMain.java:14: error: MyAccess(int) has private access in MyAccess

        MyAccess obj = new MyAccess(25);

                       ^
1 error

default

As the name defines, if we do not mention any access specifier, this is the opted access mode. Till now, every example we have seen in earlier lectures, this was the scope of the members of the class. An entity with the default access is accessible only inside the package. It will not be accessed outside the package. This mode has relatively more access than private but more strict than protected and public.

Example:

class MyAccess{
    //default access variable
      int myData;

    //default access constructor
      MyAccess(int data){
       myData=data;
     }

    //A default access method that return myData
      int getMyData(){
         return myData;
     }
}

public class ClassMain{
    public static void main(String args[]){
        MyAccess obj = new MyAccess(25);
        System.out.println("The value of myData by variable : "+ obj.myData);
        System.out.println("The value of myData by method : "+ obj.getMyData());       
    }
}

Output:

The value of myData by variable : 25
The value of myData by method : 25

Example2:

package pkgAccess;
class MyAccess{
    //default access variable
      int myData;

    //default access constructor
      MyAccess(int data){
        myData=data;
     }

     //A default access method that return myData
      int getMyData(){
         return myData;
     }
}
package pkgAccess2;
public class ClassMain{
    public static void main(String args[])
    {
        MyAccess obj = new MyAccess(25);
        System.out.println("The value of myData by method : "+ obj.getMyData());       
    }
}

Output:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
The method getMyData() from the type MyAccess is not visible
at MyAccess2. ClassMain.main(Test.java:5)

protected

The variable, method, and constructor defined as protected will be accessible everywhere in the package and outside the package only through inheritance. The purpose of protected access is to provide more access than the default. Classes(except Nested Class) and Interfaces(except Inner Interface) cannot be defined as protected

Taking the same code used in default, but inheriting MyAccess, makes it accessible in another package as well.

Example:

package pkgAccess;
class MyAccess{
    //protected access variable
     protected int myData;

    //protected access constructor
      MyAccess(int data){
        myData=data;
     }

     //A protected  access method that return myData
     protected int getMyData(){
         return myData;
     }
}
package pkgAccess2;
import pkgAccess.MyAccess; //MyAccess class of package pkgAccess is imported
public class ClassMain extends MyAccess {  // MyAccess is inherited
    public static void main(String args[])
    {
      MyAccess obj = new MyAccess(25);
      System.out.println("The value of myData by variable : "+ obj.getMyData()); 
      System.out.println("The value of myData by method : "+ obj.getMyData());       
    }
}

Output:

The value of myData by variable : 25
The value of myData by method : 25

public

The specifier that allows an entity to be accessed anywhere. It has the widest accessibility. It can be outside class, outside package, anywhere.

Example:

package pkgAccess;
class MyAccess{
    //public access variable
      public int myData;

    //public access constructor
      public MyAccess(int data){
        myData=data;
     }
    
     //A public access method that return myData
      public int getMyData(){
         return myData;
     }
}
package pkgAccess2;
public class ClassMain{
    public static void main(String args[]){
        MyAccess obj = new MyAccess(25);
        System.out.println("The value of myData by variable : "+ obj.myData);
        System.out.println("The value of myData by method : "+ obj.getMyData());       
    }
}

Output:

The value of myData by variable : 25
The value of myData by method : 25

As you can see, the member of a class MyAccess from a different package is accessible in ClassMain class only because we have made the members public to be accessed from anywhere.

This was an overview of Access Specifiers. We will discuss static and this keyword in the next lecture.