Java classes and their variables and methods can use access modifiers – private, public, protected, and package-level (no keyword). These access modifiers set the classes’ visibility, constructors, and instance or class variables and methods to the other parts of the application codes.
Top-Level Java Classes
The TopLevelClass1 class is a top-level class. It is the only public class in a .java file that has the same name – TopLevelClass1.java.
1 2 3 4 | package com.turreta.accessmodifiers; public class TopLevelClass1 { } |
Let’s say we added another public class in the same file. Now, the codes will not compile.
1 2 3 4 5 6 7 | package com.turreta.accessmodifiers; public class TopLevelClass1 { } public class TopLevelClass1New { } |
The IDE or the javac command gives out the following compile-time error.
1 | Class 'TopLevelClass1New' is public, should be declared in a file named 'TopLevelClass1New.java' |
Similarly, if we had other classes that are private and protected, the codes will fail compilation.
1 2 3 4 5 6 7 8 9 10 11 12 13 | package com.turreta.accessmodifiers; public class TopLevelClass1 { } public class TopLevelClass1New { } private class PrivateTopLevelClass { } protected class ProtectedTopLevelClass { } |
For the private class, the compiler generates the following error.
1 | Modifier 'private' not allowed here |
For the protected class, the compiler generates the following error.
1 | Modifier 'protected' not allowed here. |
However, if we only had package-level classes (those with no access modifier before the class keyword), everything works – no compilation errors.
In summary, a top-level class is a Java class that is not within any other block of codes. Moreover, it has the same name as the .java file where it is stored. Also, it can only be either a public or a package-level class. The rules also apply to Java interfaces – on later posts.
From here on, we interchangeably refer to a Java class’ instance and class variables as properties and the methods as behaviors.
Default Constructors Access Modifiers
Default constructors are constructors that the compiler inserts into our class codes during compilation when we don’t create our constructors. A default constructor’s default access modifier is the class’ access modifier.
Consider the following package-level class.
For a class with a package-level access modifier, its default constructor will have the same access modifier.
The Four Access Modifiers in Java
There are four access modifiers that we can use on classes, both instance, and static variables and methods. They set the visibility of the class itself and its variables and methods to the other parts of the program. If they aren’t visible, the other codes won’t use them, and the compilation will fail. In Java, there are four access modifiers.
The private Access Modifier
The private access modifier makes an instance or class variables and methods visible only to the codes within the class. Consider the following Java class with both a private property and a private method that are not visible to other codes.
1 2 3 4 5 6 7 8 9 10 11 | package com.turreta.accessmodifiers; public class TopLevelClassForPrivateAccessModifier { private String petName; private void printPetName() { System.out.println(this.petName); } } |
Now, we have the StartupClass class that uses the TopLevelClassForPrivateAccessModifier class’s property and method.
1 2 3 4 5 6 7 8 9 | package com.turreta.accessmodifiers; public class StartupClass { public static void main(String[] args) { TopLevelClassForPrivateAccessModifier pam = new TopLevelClassForPrivateAccessModifier(); pam.petName = "Apet"; pam.printPetName(); } } |
When we run these codes, we will get compilation errors.
1 2 | Error:(6, 12) java: petName has private access in com.turreta.accessmodifiers.TopLevelClassForPrivateAccessModifier Error:(7, 12) java: printPetName() has private access in com.turreta.accessmodifiers.TopLevelClassForPrivateAccessModifier |
The TopLevelClassForPrivateAccessModifier class’ property and method are not visible to the StartupClass class. On the other hand, if we moved the main method to the TopLevelClassForPrivateAccessModifier class and run it, the codes compile, and the application runs successfully.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package com.turreta.accessmodifiers; public class TopLevelClassForPrivateAccessModifier { private String petName; private void printPetName() { System.out.println(this.petName); } public static void main(String[] args) { TopLevelClassForPrivateAccessModifier pam = new TopLevelClassForPrivateAccessModifier(); pam.petName = "Apet"; pam.printPetName(); } } |
The public Access Modifier
The public access modifier makes the class itself, its instance, or class variables and methods visible to all other codes. Consider the following new class.
1 2 3 4 5 6 7 8 9 10 11 | package com.turreta.accessmodifiers; public class TopLevelClassForPublicAccessModifier { public String carMake; public void printCarMake() { System.out.println(this.carMake); } } |
Next, we modify our StartupClass class to use the new Java class.
1 2 3 4 5 6 7 8 9 | package com.turreta.accessmodifiers; public class StartupClass { public static void main(String[] args) { TopLevelClassForPublicAccessModifier pam = new TopLevelClassForPublicAccessModifier(); pam.carMake = "Toyota"; pam.printCarMake(); } } |
The codes compile and run successfully.
The no-keyword Package-Level Access Modifier
The package-level access modifier does not have a keyword compared to the other access modifiers. The class’ constructors, properties, and methods are visible to codes in the same package with the package-level access modifier. Consider the following class in package com.turreta.accessmodifiers.package1.
1 2 3 4 5 6 7 8 9 10 11 | package com.turreta.accessmodifiers.package1; public class TopLevelClassForProtectedAccessModifier { protected String animalName; protected void printAnimalName() { System.out.println(this.animalName); } } |
Our modified StartupClass class is a different from that of TopLevelClassForProtectedAccessModifier.
1 2 3 4 5 6 7 8 9 10 11 | package com.turreta.accessmodifiers; import com.turreta.accessmodifiers.package1.TopLevelClassForProtectedAccessModifier; public class StartupClass { public static void main(String[] args) { TopLevelClassForProtectedAccessModifier pam = new TopLevelClassForProtectedAccessModifier(); pam.animalName = "Lion"; pam.printAnimalName(); } } |
When we compile these codes, we get the following errors.
1 2 | Error:(8, 12) java: animalName has protected access in com.turreta.accessmodifiers.package1.TopLevelClassForProtectedAccessModifier Error:(9, 12) java: printAnimalName() has protected access in com.turreta.accessmodifiers.package1.TopLevelClassForProtectedAccessModifier |
Suppose we moved StartupClass to the com.turreta.accessmodifiers.package1 package; the codes will compile and run successfully.
1 2 3 4 5 6 7 8 9 10 11 | package com.turreta.accessmodifiers.package1; //import com.turreta.accessmodifiers.package1.TopLevelClassForProtectedAccessModifier; public class StartupClass { public static void main(String[] args) { TopLevelClassForProtectedAccessModifier pam = new TopLevelClassForProtectedAccessModifier(); pam.animalName = "Lion"; pam.printAnimalName(); } } |
The protected Access Modifier
The protected access modifier works like the package-level access modifier. In addition to that, it works with inheritance and bypasses the package-level access restriction. Consider the following classes.
1 2 3 4 5 6 7 8 9 | package com.turreta.accessmodifiers.package3.a; public class ProtectedAccessModifierClass { protected String personName; protected void printPersonName() { System.out.println(this.personName); } } |
The ProtectedAccessModifierClass class has a protected property and a protected method. Then, we create another class that extends ProtectedAccessModifierClass.
1 2 3 4 5 6 7 8 9 10 11 | package com.turreta.accessmodifiers.package3.b; import com.turreta.accessmodifiers.package3.a.ProtectedAccessModifierClass; public class ChildProtectedAccessModifierClass extends ProtectedAccessModifierClass { public static void main(String[] args) { ChildProtectedAccessModifierClass child = new ChildProtectedAccessModifierClass(); child.printPersonName(); } } |
Although ChildProtectedAccessModifierClass is in a different package from ProtectedAccessModifierClass, the child class has access to the parent class’s property and method via inheritance.
If we had another class that accesses the ProtectedAccessModifierClass class’s property and method, that class would fail compilation.
The Case Of Inner Classes In Java
We can nest Java classes. If we top-level classes, we also have inner classes that we define within other classes. These classes can be either instance or static classes.
What’s Next?
We have tackled Java Classes And Access Modifiers, but we only have scratched the surface of Java. Before we go any further, we ought to know what Java primitives are. They are data types that we cannot create objects of because they are non-OOP.