Access Modifiers in Java
Java Access Specifiers (also known as Visibility Specifiers) regulate access to classes, fields and methods in Java. They can also be called Access Modifiers. They are usually keywords that determine the accessibility of class, fields and methods in a program. Here the class has control over what data or information is accessed by other classes.
These Specifiers determine whether a field or method in a class can be used or invoked by another method in another class or sub-class. Access Specifiers can also be used to restrict access. Access Specifiers are an integral part of object-oriented programming. In basic terms, they curb access.
There are four Access Specifiers in Java:
- Public
- Private
- Default
- Protected
Public
- It can be applied to constructor, global variables, static variables, methods, inner classes or outer classes
- Public members are accessible everywhere, in same class, outside the class, or any package
- Local variables cannot be public as they already have a scope within the method
Private
- A class cannot be private
- Private access specifier can be applied to global variable, method, constructor and inner class only
- Local variables cannot be private but global variables can be private
- Private members can be accessed only within the enclosed brackets
- The program below will give the error
- Here, we see that the variable is private and not accessible in other classes
package com.javabykiram.encapsulation.accessSpecifier;
class A1 {
private int var = 90;
void testVar() {
A1 a = new A1 ();
System.out.println(a.var); //No Error
}
}
class B {
void testVar() {
A1 a = new A1 ();
//System.out.println(a.var);
//the field a.var is not visible as it is private
}
}
If we make constructor private, we cannot create an object of that class from other classes
Question that may be asked - How you will stop others from creating object of your class? The answer would be: By making constructor private.[this will be more clear in constructor chapter]
In the below given example we may have confusion that
Local variable is not equivalent to instance variable
Local variables cannot be static
private A a1=new A();- This statement means a1 address is not visible outside, hence, we are not able to access it from outside
- Remember, there will be no impact to class A
- We can't say that class A is private. By this line it's just a variable ‘a1’ is private
Example
package com.javabykiran.Encapsulation.accessSpecifier;
class A {
int jbk = 90;
}
class VarEx {
public A a = new A();
private A a1 = new A();
}
class TestVarEx {
public static void main(String[] args) {
VarEx varex = new VarEx();
System.out.println(varex.a.jbk);
//System.out.println(varex.a1.jbk);
// wrong, a1 is private
}
}
Question: Why should you know private variable? Where have you used in your project?
Answer: :Let’s say we have the following requirement:In a college we want to insert student details and one student insertion means that is:
- Qualification should be inserted
- Personal details should be inserted
- Skills should be inserted
- Fee details should be inserted
Now we will start writing a simple class where the above specified requirements will be fulfilled
First approach:
package com.javabykiran.Encapsulation.accessSpecifier;
public class Student {
public void insertStudent() {
// some code for Qual
// logic for Qual insertion
// some code for Personal Detail
// logic for Personal Detail insertion
// some code for Skills
// logic for Skills insertion
// some code for Fees
// logic for Fees insertion
}
}
This approach will not be accepted as all code written is at one place. If, in the future, we want to make fees optional, it won’t be possible and we will need to change whole code which increases unit testing. The above written code will work properly at the first instance, but if we think for the future, then it will be difficult to manage it.
So, we need to change this code as shown below again:
Second approach:
package com.javabykiran.Encapsulation.aceessspecifier;
public class Student {
public void insertStudent() {
insertQual();
insertPD();
insertSkill();
insertFees();
}
public void insertQual()
{
//------
System.out.println("Qualification");
//------
}
public void insertPD()
{
//------
System.out.println("Personal Details");
//------
}
public void insertSkill()
{
//------
System.out.println("Skill Details");
//------
}
public void insertFees()
{
//------
System.out.println("Fees Details");
//------
}
}
In this approach, we just tried to bring more readability and modularity in our code. That means we will have less maintenance. This is just code writing in a different way. It is just copy and pasting code at different places. Now, consider that after some years we want to remove skill insertion. We will then need to comment only one line.
public void insertStudent() {
insertQual();
insertPD();
// insertSkill();
insertFees();
}
Still, our code gets rejected as requirement is not completely fulfilled. HOW??
The client can call any methods directly from outside and can insert anything like fees, etc. But requirement says that all methods should get called so that student will get inserted with all details not just a single or partial detail.
Third approach:
package com.javabykiran.Encapsulation.aceessspecifier;
public class Student {
public void insertStudent()
{
insertQual();
insertPD();
insertSkill();
insertFees();
}
//all below methods are private
private void insertQual()
{
//------
System.out.println("Qualification");
//------
}
private void insertPD()
{
//------
System.out.println("Personal Details");
//------
}
private void insertSkill()
{
//------
System.out.println("Skill Details");
//------
}
private void insertFees()
{
//------
System.out.println("Fees Details");
//------
}
}
This is the most correct approach as all other methods are private and only one method is public which can be accessed from outside.
So, nobody can call any method directly without going through insertStudent method. That's what the requirement says.
Here, it must be noticed how access specifiers play an important role.
If we use them properly, our code will be more managed in the long run.
Default
- When an access specifier is not specified to members of a class, then it is called default
- Default members can be accessible only within same package or folder
- Default can be applied to constructor, global variable, local variable, methods, inner classes, outer classes etc.
- Default is a keyword in java. We may mistakenly think that it is an access specifier, but it actually is for a switch statement
Protected
- It can be applied to constructor, global variable, methods
- It cannot apply to outer classes, but can be applied to inner classes
- It cannot apply to the local variable
- Protected members are accessible within same package and another package of its subclass only. Inheritance must be there, the caller of protected members is the subclass of protected member’s class.
If any method is overridden from super class to sub class, then the access specifier of the overridden method must be protected or public.
To know this completely, we must know inheritance in detail,please go through inheritance chapter
| Private | No Modifier | Protected | Public | |
|---|---|---|---|---|
| Same class | Yes | Yes | Yes | Yes |
| Same package sub-class | No | Yes | Yes | Yes |
| Same package non-subclass | No | Yes | Yes | Yes |
| Different package subclasses | No | No | Yes | Yes |
| Different package non-subclass | No | No | No | Yes |