CodeGym/Java Blog/Keywords in Java/Access Modifiers in Java
Author
Artem Divertitto
Senior Android Developer at United Tech

Access Modifiers in Java

Published in the Keywords in Java group
members
Hi! In today's lesson, we'll get acquainted with the concept of access modifiers and consider examples of how to work with them. Of course, saying 'get acquainted' isn't quite right: you are already familiar with most of them from previous lessons. Just in case, let's refresh our memory of the most important point. Modifiers access are most often keywords that regulate access to different parts of your code. Why 'most often'? Because one of them is set by default without the use of a keyword :) Java has four access modifiers. We list them in order from most restrictive to most 'lenient':
  • private;
  • default (package visible);
  • protected;
  • public.
Let's take a look at each of them and identify when they might be useful. And we'll give examples :)

The private modifier

Access modifiers. Private, protected, default, public - 2private is the most restrictive access modifier. It limits the visibility of data and methods to within a single class. You know this modifier from the lesson about getters and setters. Remember this example?
public class Cat {

   public String name;
   public int age;
   public int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
We considered it in a previous lesson. We made a serious mistake here: We make our data public, which allowed fellow programmers to access the fields directly and change their values. What's more... these values were assigned without any checks. This means that our program could create a cat named "" with an age of -1000 years and weight of 0. To solve this problem, we used getters and setters, and also used the private modifier to limit access to the data.
public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       // input parameter check
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       // input parameter check
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       // input parameter check
       this.weight = weight;
   }
}
Basically, limiting access to fields and implementing getters and setters are the most common examples of how private would be used in real work. In other words, the main purpose of this modifier is to achieve encapsulation in a program. This doesn't apply only to fields, by the way. Imagine that in your program has a method that implements some VERY complex functionality. What can we suggest as an example? Let's say your readDataFromCollider() method accepts as input a data address, reads data from the Large Hadron Collider in byte format, converts this data into text, writes it to a file, and prints it. Even a description of the method looks scary, to say nothing of the code :) To make the code more readable, it would be best to not write all the method's complex logic in one place. Instead, we should break apart the functionality into separate methods. For example, the readByteData() method is responsible for reading data, the convertBytesToSymbols() method converts the data read from the collider into text, the saveToFile() method saves the received text to a file, and the printColliderData() method prints our data file. In the end, our readDataFromCollider() method will be much simpler:
public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   public byte[] readByteData(Path pathToData) {

       // Reads data in bytes
   }

   public String[] convertBytesToSymbols(byte[] colliderDataInBytes) {

       // Converts bytes to characters
   }

   public File saveToFile(String[] colliderData) {

       // Saves read data to a file
   }

   public void printColliderData(File fileWithColliderData) {

       // Prints data from the file
   }
}
However, as you'll remember from the lesson about interfaces, the user only gets access to the external interface. And our 4 methods are not part of it. They are helper methods: we created them to improve the readability of the code and to not cram four different tasks into one method. You don't need to give the user access to these methods. If users have access to the convertBytesToSymbols() method when working with the collider, they will most likely simply be confused by the method and wonder what it's for. What bytes are converted? Where did they come from? Why convert them to text? The logic executed in this method is not part of the interface exposed to the user. Only the readDataFromCollider() method is part of the interface. So what do we do with these four 'internal' methods? Right! Use the private modifier to limit access to them. Doing this allows them to peacefully perform their work inside the class without confusing the user, who doesn't need to know the logic of each individual method.
public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   private byte[] readByteData(Path pathToData) {
       // Reads data in bytes
   }

   private String[] convertBytesToSymbols(byte[] colliderDataInBytes) {
       // Converts bytes to characters
   }

   private File saveToFile(String[] colliderData) {
       // Saves read data to a file
   }

   private void printColliderData(File fileWithColliderData) {
       // Prints data from the file
   }
}

The protected modifier

The next most restrictive modifier is protected. Access modifiers. Private, protected, default, public - 3Fields and methods marked by the protected access modifier will be visible:
  • within all classes included in the same package as ours;
  • within all classes that inherit our class.
At first, it's hard to imagine when this might be needed. Don't be surprised: there are far fewer use cases for protected than for private, and they are very specific. Imagine that we have an AbstractSecretAgent abstract class that represents a secret agent in some intelligence service, as well as a top_secret package that contains this class and its descendants. Concrete classes such as FBISecretAgent, MI6SecretAgent, MossadSecretAgent, etc. inherit it. Inside the abstract class, we want to implement an agent counter. It will increase when a new agent is created somewhere in the program. package top_secret;
public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
But our agents are secret! This means that they and no one else should know how many of them exist. We can easily add the protected modifier to the agent_counter field. Then instances of other secret agent classes and other classes located in our top_secret package can get its value.
public abstract class AbstractSecretAgent {

   protected static int agent_counter = 0;
}
And that's the sort of specialized task that requires the protected modifier :)

The package visible modifier

Next on the list is the default modifier, also known as the package visible modifier. It's not indicated by a keyword, since Java applies it by default to all fields and methods. If you write the following in your code:
int x = 10
the x variable will have this package visible access. It's easy to remember what it does. Basically, default = protected inheritance :) Like the protected modifier, its application is limited. Most often, default access is used in a package that has some utility classes that don't implement the functionality of all the other classes in the package. Let's give an example. Imagine that we have a 'services' package. It contains various classes that work with a database. For example, there's a UserService class that reads user data from the database, a CarService class that reads car data from the same database, and other classes, each of which works with specific types of objects and reads corresponding data from the database.
package services;

public class UserService {
}

package services;

public class CarService {
}
But it would be easy for the data in the database to be in one format and we need it in another. Imagine that users' birthdates in the database is stored as <TIMESTAMP WITH TIME ZONE>...
2014-04-04 20:32:59.390583+02
...and instead we need the simplest object — a java.util.Date. To solve this problem, inside the services package, we can create a special Mapper class. It will be responsible for converting data from the database into our familiar Java objects. A simple helper class. We usually declare all classes as public class ClassName, but this isn't a requirement. We can declare our helper class simply as class Mapper. In this case, it still does its job, but it isn't visible to anyone outside the services package!
package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
And here's the basic reasoning: why would anyone outside a package need to see a helper class that only works with the classes in that package?

The public modifier

And last but not least, the public modifier! You met this modifier on your first day of study on CodeGym the first time you ran public static void main(String[] args). Access modifiers. Private, protected, default, public - 4Now that you've studied the lesson about interfaces, its purpose is obvious to you :) After all, the public modifier was created to give something to users. For example, your program's interface. Suppose you've written a translator program that can translate Russian text into English. You created a translate(String textInRussian) method that implements all the necessary logic. You marked this method with the word public, and now it's part of the interface:
public class Translator {

   public String translate(String textInRussian) {

       // Translates text from Russian to English
   }
}
You can bind this method to the 'Translate' button on the screen and you're done! Anyone can use it. The parts of code marked with the public modifier are intended for the end user. Providing a real-life example, private is for all processes that occur inside a TV, but public is for the buttons on the remote control used to manage the TV. What's more, the user doesn't need to know how the television is built or how it works. The remote control is the set of public-methods: on(), off(), nextChannel(), previousChannel(), increaseVolume(), decreaseVolume() etc. To reinforce what you learned, we suggest you watch a video lesson from our Java Course
Comments (14)
  • Popular
  • New
  • Old
You must be signed in to leave a comment
Tasmoda Android Developer
20 June 2022, 18:01
Nice article!😉
Anatoly
Level 17
1 March 2021, 01:12
What about "final" access modifier. Why there is nothing about it?
Lydia
Level 25 , Netherlands
10 November 2021, 08:25
'final' is not about access, it's about mutability
Andrei
Level 41
7 December 2020, 12:20
I don't understand something:
package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
Why is package services declared 2 times?
Bodea Tudor Andrei
Level 25 , Cluj-Napoca, Romania
9 January 2021, 15:58
Hi there! It is a bit weird maybe the example I'm gonna give it to you but here it is: So in the examples from codeGym you are probably used to see this:
package org.codegym.something

public class MainClass {
    public static void main(String[] args) {
    }

    public static class AnotherClass{
<variables>
<constructors>
<methods>
<getters>/ <setters>
}
Now the main thing is to observe the package I've wrote with bold. As I said you are used to see "classes inside classes" by that I mean that the "AnotherClass" class is a static one. And it is like that in almost all examples they give us and in the exercises as well so that the program can compile. If it were to be just "public class AnotherClass" if you were trying to make something like this:
public class MainClass {
    public static void main(String[] args) {
            AnotherClass anotherClass = new AnotherClass;
    }
The code would not compile because the static keyword is not present. NOW all this being say back to what you want to find out, indeed the example you've put there doesn't have a "static" keyword and that is because most of the time when you write programs in Java you will create individual classes in the package, you know the good old "Right click on the desired package -> New -> Java Class etc." and every class besides it's "public class className" will first have the package name. And in the code you've provided it's just so we can better understand / read the code. Normally those would've been 2 different classes in the "services" package something like this:
package services;

class Mapper {
}
package services;

public class CarService {
   Mapper mapper;
}
I hope you understand! 😁
Andrei
Level 41
11 January 2021, 09:15
Thanks, it makes sense now! 😁
Edddieg
Level 15 , Providence, United States
6 November 2020, 21:06
cool
zendro
Level 22 , Hungary
11 September 2019, 17:33
The default (package visible) is more restrictive than the protected.
Piotr Wikarski
Level 19 , Birmingham, United Kingdom
14 October 2019, 12:25
Why did they put it in wrong order..?
Fadi Alsaidi
Level 34 , Carrollton, TX, USA
1 February 2020, 14:37
you are absolutely right. I emailed the staff to bring it to their attention
Alex Vypirailenko Java Developer at Toshiba Global Comme
1 February 2020, 14:53
Fixed.
Strafer
Level 25 , United States
29 December 2022, 20:43
This has been fixed in the intro text where the access modifiers are first listed, however the body of the article still has the protected and default topics out of order.
KIN SOCHEAT
Level 34 , Phnom Penh, Cambogia
4 September 2019, 05:42
Yes nice example
Kisszol
Level 15 , Toeroekbalint, Hungary
7 May 2019, 14:41
Bona artikolo por rememori la kontenton :)