Public, Private, Protected Access Modifiers and No Modifiers in Java
Table of Contents
Levels of Access | Private | No Modifier | Protected | Public |
---|---|---|---|---|
Same Class | Yes | Yes | Yes | Yes |
Same Package Sub Class | No | Yes | Yes | Yes |
Same Package Non-Sub Class | No | Yes | Yes | Yes |
Different Package Sub Class | No | No | Yes | Yes |
Differnt Package Non-Sub Class | No | No | No | Yes |
Note – In this table, Sub Class means a child-parent relationship is involved between the two classes.
If you do not understand the above table, do not worry because you will understand it after going through the complete article.
Why I am writing this in-depth article
After discussing Interfaces in our last article, today we will discuss the access modifiers in detail. This article is going to be very long because I will be explaining everything in depth. When I was studying, I found it very challenging to get one article explaining all the access modifiers and all the scenarios in a single article. I had to go through the books and many internet articles on public, private, and protected modifiers independently. The people who write the articles may have less time or care about the number of articles in their blog. Whatever the reason is, I felt the need to write an article that explains all the access modifiers in depth.
Please note that Java is a case-sensitive programming language, so all of these access modifiers can be used in all lower case while developing an application. Anywhere if I mention public private protected in upper-case, please ignore it.
BEFORE WE START, YOU NEED TO KEEP IN MIND THAT ACCESS MODIFIERS, ACCESS SPECIFIERS, SCOPE MODIFIERS, AND SCOPE SPECIFIERS ARE THE SAME THING. DO NOT GET CONFUSED WITH DIFFERENT NAMES.
Why Do We Need Access Modifiers
Suppose if you have the most crucial diamond in this world, where will you keep it? If your answer is the safest place, you can find. You are correct because losing the diamond is your biggest loss. The same goes for the data when we start developing an application. If you talk to the person you are developing this application for, he does not understand technical stuff, but his only data is his data.
It would help if you made sure that, in any case, the data can not be left unprotected. Since you are a programming language student, you understand the data flow in the classes like blood in our veins. We need to deploy protection and limit access. When we talk about limiting access, we are talking about limiting access to the other classes. To achieve this limitation, we use access modifiers.
Levels of Access Limitation
There are two levels of limitation in Java.
- Class Level Access Limitation
- Package Level Access Limitation
Class Level Limitation
Class Level Access Limitation means you do not want your data to be accessed outside a particular class. Here we need to keep in mind when we talk about data; we are talking about methods and variables that should not be accessed outside a class. There will be scenarios where you do not want a method or a variable to be accessed outside a class. There are other techniques to set the value of a variable or get the outcome of a method from a class without accessing the method directly. Some of those techniques are setters and getters. We will talk about setter and getters in a separate article because this article is about access modifiers.
Package Level Limitation
Before we start talking about package level limitations, we need to understand what a package is and why we need it.
What is a package and why we need it?
The package means a folder or a directory. As you know, the code that we write in java is inside a class. A class is a file that is saved on our hard drive with the extension as .java. You know the class names can not be the same because there will be a naming conflict, and our main method will not understand which class it needs to pick and run.
In the small application, you can easily deal with this problem by choosing different names for your classes because you are the only programmer working on this application. But think about a big organization where hundreds of programmers are working, and you will see dozens of people are working to develop the same application. Imagine your colleague is fighting with you over the name of a class. He says, why did you choose the class name Employee.java. He wants to keep his class name as Employee.java, but he can not use the same name because you have already used it.
To solve this problem, the developers of Java introduced the package names. A package is a folder (directory) created on the hard drive, and you can keep all relevant classes inside that one directory. By using packages, you don’t need to worry about the naming conflicts because your class is in a unique folder, and every time some other class needs to use the class you made, that class needs to import the package name first and then only that class can use your class. Due to unique package names, the Java compilers will easily understand where to look for a particular class. The class name does not matter now because the class is inside a package and the package name is the identity for all the classes inside this package.
Now you need to keep in mind that you are not using the same class names inside the same package.
Additionally, these packages provide a second layer of protection where we can use the appropriate modifier and limit the access of the class components such as variables and methods on the package level. We will be able to understand how to choose an appropriate access modifier once we understand all the access modifiers and understand our need for limiting access in the application we are developing.
Now that we have understood the levels of access limitation, it’s time to talk about all access modifiers and their functionality. We will start with a public access modifier first.
public
The public access modifier is the most famous one. This one gives the maximum level of access. If a class or variable or a method is public, it can be accessed at all levels. All level means all levels mentioned in the table on the top of this article. For your ease, I am mentioning it below as well.
Levels of Access |
---|
Same Class |
Same Package Sub-Class |
Same Package Non-Sub-Class |
Different Package Sub-Class |
Different Package Non-Sub-Class |
To understand the public access modifiers, let us create a small program for each level.
The public Access Modifier Same Class Scenario
ClassA Code
package mainPackage.Parent;
public class ClassA {
public String message = "Fun Method Statement from ClassA";
public void Fun() {
System.out.println(message);
}
}
Main Class Code
package mainPackage;
import mainPackage.Parent.ClassA;
public class Hello {
public static void main(String[] args) {
ClassA classA = new ClassA();
classA.Fun();
}
}
Program Output
Fun Method Statement from ClassA
Explanation
As you can see, the string variable message and Fun() method are inside the same ClassA. The String variable message has the access modifier as public, and it is being used inside the Fun() method in the same class. There is no error at all.
We only need to import a package if we use a class that exists in a different package.
The public Access Modifier Same Package Sub-Class
ClassA Code
package mainPackage.Parent;
public class ClassA {
public void Fun() {
System.out.println("Fun Method Statement from ClassA");
}
}
ClassB Code
package mainPackage.Parent;
public class ClassB extends ClassA {
public void Fun() {
System.out.println("Fun Method Statement from ClassB");
}
}
Main Class Code
package mainPackage;
import mainPackage.Parent.ClassA;
import mainPackage.Parent.ClassB;
public class Hello {
public static void main(String[] args) {
ClassA classB = new ClassB();
classB.Fun();
}
}
Program Output
Fun Method Statement from ClassB
Explanation
You can see the ClassA and ClassB are in the same package as mainPackage.Parent and they are in Child parent relationship because ClassB extends ClassA. Both ClassA and ClassB are in use, so we need to import their packages as well. Once we import their packages, the ClasssB function is available when we create an object of ClassB and save that object in the variable type of ClassA type.
The public Access Modifier Same Package Non-Sub-Class
ClassA Code
package mainPackage;
public class ClassA {
public void Fun() {
System.out.println("Fun Method Statement from ClassA");
}
}
Hello Class Code with Main Method
package mainPackage;
public class Hello {
public static void main(String[] args) {
ClassA classA = new ClassA();
classA.Fun();
}
}
Program Output
Fun Method Statement from ClassA
Explanation
Both the ClassA and the Hello class are available in the same package. They have no child-parent relationship. Because the Fun() method of ClassA has access modifier as public, the method is available to use in the Hello class.
The public Access Modifier Different Package Sub-Class
ClassA Code
package mainPackage.Parent;
public class ClassA {
public void Fun() {
System.out.println("Fun Method Statement from ClassA");
}
}
ClassB Code
package mainPackage.Child;
import mainPackage.Parent.ClassA;
public class ClassB extends ClassA{
public void Fun() {
System.out.println("Fun Method Statement from ClassB");
}
}
Hello Class with Main Method Code
package mainPackage;
import mainPackage.Child.ClassB;
import mainPackage.Parent.ClassA;
public class Hello {
public static void main(String[] args) {
ClassA classA = new ClassB();
classA.Fun();
}
}
Program Output
Fun Method Statement from ClassB
Explanation
ClassA and ClassB are in different packages; ClassA is inside package mainPackage.Parent and ClassB is inside package mainPackage.Child. ClassB is a subclass of ClassA. The Fun() method inside ClassB is visible to ClassA due to the access modifier as public.
The public Access Modifier Different Package Non-Sub-Class
ClassA Code
package mainPackage.Parent;
public class ClassA {
public void Fun() {
System.out.println("Fun Method Statement from ClassA");
}
}
Hello Class with Main Method
package mainPackage;
import mainPackage.Parent.ClassA;
public class Hello {
public static void main(String[] args) {
ClassA classA = new ClassA();
classA.Fun();
}
}
Program Output
Fun Method Statement from ClassA
Explanation
The Hello Class with Main Method and ClassA are in different packages, and they have no child-parent relationship, yet ClassA Fun() method is available because it has access modifier as public. Due to different packages importing the ClassA package is mandatory.
private
This is the time to discuss the private access modifier. Private access modifier is almost the opposite of public access modifier because it restricts access on all levels class, and package. It only allows access inside the same class. If a variable or method is declared as private, it can not be accessed outside the class in any situation.
Level of Access |
---|
Same Class |
The private Access Modifier Same Class
ClassA Code
package mainPackage.Child;
public class ClassB {
public void Fun() {
System.out.println("Fun Method Statement from ClassB");
}
}
Hello Class with Main Method
package mainPackage;
public class Hello {
public static void main(String[] args) {
ClassA classA = new ClassA();
classA.Fun();
}
}
Program Output
Fun Method Statement from ClassB
Explanation
As you can see, the message variable inside ClassA is a local string variable message. It can easily be assessed by the Fun() method inside the ClassA because both ClassA and string variables exist in the same class. But if we try to access the private variable message outside ClassA, it will not be accessed, and the following error will occur.
Exception in thread “main” java.lang.Error: Unresolved compilation problem:
The field ClassA.message is not visible
at mainPackage.Hello.main(Hello.java:8)
Inside the class is the only way to access private property or method. There is no other way.
protected
In terms of a protected modifier, we need to keep one thing in mind. There is only one situation in which the property or method will not be accessible, and that one situation is.
In every other situation, we can access the property or method except the situation mentioned above. If you want the property to be accessed outside a class, you will have to maintain at least one relationship, either the same package or child-parent relationship or both.
The protected Access Modifier Same Class
ClassA Code
package mainPackage.Parent;
public class ClassA {
protected String message = "Message from ClassA";
protected void Fun() {
System.out.println(message);
}
}
Hello Class with Main Method Code
package mainPackage;
import mainPackage.Parent.ClassA;
public class Hello {
public static void main(String[] args) {
ClassA classA = new ClassA();
classA.Fun();
}
}
Program Output
Message from ClassA
Explanation
Despite the String variable being protected, it is accessible to the Fun() method. The Fun() method is protected. Because both the variable and the Fun() method are inside the same class, that is why it is possible.
The protected Access Modifier Same Package Sub-Class
ClassA Code
package mainPackage.Parent;
public class ClassA {
protected String message = "Message from ClassA";
protected void Fun() {
System.out.println(message);
}
}
ClassB Code
package mainPackage.Parent;
import mainPackage.Parent.ClassA;
public class ClassB extends ClassA {
protected void Fun() {
System.out.println("Fun Method Statement from ClassB");
}
}
Hello Class with Main Method
package mainPackage.Parent;
import mainPackage.Parent.ClassA;
public class Hello {
public static void main(String[] args) {
ClassA classB = new ClassB();
classB.Fun();
}
}
The output of the Program
Fun Method Statement from ClassB
Explanation
All the classes Hello, ClassA and ClassB exist in the same package. ClassB is a subclass of ClassA. The Fun() method in the ClassB is protected but yet accessible out of the class. There are two reasons for accessibility. One is they are in the same package, and another is they are in the child-parent relationship.
The protected Access Modifier Same Package Non-Sub-Class
ClassA Code
package mainPackage.Parent;
public class ClassA {
protected String message = "Message from ClassA";
protected void Fun() {
System.out.println(message);
}
}
ClassB Code
package mainPackage.Parent;
import mainPackage.Parent.ClassA;
public class Hello {
public static void main(String[] args) {
ClassA classA = new ClassA();
classA.Fun();
}
}
The Output of the Program
Message from ClassA
Explanation
The Fun() method is accessible because one condition is fulfilled: both the ClassA and the Hello class are in the same package.
The protected Access Modifier Different Package Sub-Class
ClassA
package mainPackage.Parent;
public class ClassA {
protected String message = "Message from ClassA";
}
ClassB
package mainPackage.Child;
import mainPackage.Parent.ClassA;
public class ClassB extends ClassA {
protected String MessagefromDaughter = message;
public String getMessagefromDaughter() {
return MessagefromDaughter;
}
}
Hello Class with Main Method
package mainPackage;
import mainPackage.Child.ClassB;
import mainPackage.Parent.ClassA;
public class Hello {
public static void main(String[] args) {
ClassB classB = new ClassB();
System.out.println(classB.getMessagefromDaughter());
}
}
Result
Message from ClassA
Explanation
As you can see, the string variable called message is a protected variable in ClassA. The message-protected variable is accessible inside Child class ClassB because ClassB is a child class of ClassA.
You must be thinking, why did I not access the message variable of ClassA directly in the Hello class by creating a ClassB object. The reason is that the protected access modifier says the protected object will not be accessible if the package of other classes is different. There is no child-parent relationship between the two classes. The two classes we are talking about are –
- The first is where the protected property is located. In this example it is ClassA.
- The second is where the protected property is being accessed. In this example, it is the Hello class.
Please read further explanation very carefully.
The OOPs Rule - When two classes are in the child-parent relationship. If you create an object of child class it is like creating an object of the parent class.
The protected access modifier rule - In order to access a protected object we need to maintain at least one relationship, either the other class should be in the same package or the other class should be a subclass.
The ClassA is not a child class of Hello class. Instead, ClassA is a parent class of ClassB. So only ClassB can access the properties of ClassA, not Hello class. When we create an object of ClassB, the compiler understands as if we have created an object of ClassA; this is why it does not allow the access of ClassA protected property because ClassA is in a different package, and there is no child-parent relationship between Hello class and ClassA. I hope you have understood the example and explanation.
The protected Access Modifier Different Package, Non-Sub-Class
This is the only situation where a protected variable or method can not be accessed. The protected access modifier says that there should be at least one relationship maintained.
The other class should be in the same package, or the other class should be in a child-parent relationship. If someone tries to access such property that does not follow the above rule, the compiler will give the same error that the protected property or method is not visible.
The Default Access Modifier or No Modifier
With this modifier, property or method can be accessed as long as the host class is in the same package as the class accessing the No modifier property.
The default or no Access Modifier Same Class
The Hello Class with Main Method
package mainPackage;
public class Hello {
String message = "Message from Hello Class";
public static void main(String[] args) {
Hello hello = new Hello();
System.out.println(hello.message);
}
}
Result
Message from Hello Class
Explanation
The above example shows that the string variable message has no access modifier, but it is accessible inside the same class by creating the object of the Hello class.
The default or no Access Modifier Same Package Sub-Class
ClassA Code
package mainPackage.Parent;
public class ClassA {
String message = "Message from ClassA";
}
ClassB Code
package mainPackage.Parent;
import mainPackage.Parent.ClassA;
public class ClassB extends ClassA {
String messageofClassB = message;
void ClassBMessage() {
System.out.println(messageofClassB);
}
}
The Hello Class with Main Menu
package mainPackage.Parent;
import mainPackage.Parent.ClassB;
public class Hello {
public static void main(String[] args) {
ClassB classB = new ClassB();
classB.ClassBMessage();
}
}
Result
Message from ClassA
Explanation
As you can see in the above example, the string variable message is being accessed in the Hello class through the method of ClassB. Both variables and methods have no access modifier. This is possible due to two reasons.
- All the classes are in the same package.
- ClassA and ClassB are in child-parent relationships.
The default or no Access Modifier Same Package Non-Sub-Class
ClassA Code
package mainPackage.Parent;
public class ClassA {
String message = "Message from ClassA";
}
The Hello Class with Main Method
package mainPackage.Parent;
public class Hello {
public static void main(String[] args) {
ClassA classA = new ClassA();
System.out.println(classA.message);
}
}
Message from ClassA
Explanation
The string variable in ClassA is without any access modifier but still accessible in Hello class; this is possible because the Hello class and ClassA are in the same package.
Conclusion
I hope the above examples are helpful and will assist you in understanding the access modifiers in detail. Let us meet in the next article. Till then take care.
LinuxAndUbuntu Newsletter
Join the newsletter to receive the latest updates in your inbox.