JavaRush /Java Blog /Random EN /access modifiers. Private, protected, default, public

access modifiers. Private, protected, default, public

Published in the Random EN group
Hello! In today's lecture we will get acquainted with the concept of “ access modifiers ” and look at examples of working with them. Access modifiers.  Private, protected, default, public - 1Although the word “let’s get acquainted” will not be entirely correct: you are already familiar with most of them from previous lectures. Just in case, let's refresh our memory about the main thing. Access modifiers are most often keywords that regulate the level of access to different parts of your code. Why "most often"? Because one of them is set by default and is not indicated by a keyword :) There are a total of four access modifiers in Java. We list them in order from the most strict to the most “soft”:
  • private;
  • protected;
  • default(package visible);
  • public.
Let's look at each of them, decide when they can be useful to us and give examples :)

Modifier private

Access modifiers.  Private, protected, default, public - 2Private— the most restrictive access modifier. It limits the visibility of data and methods within a single class. You know this modifier from the lecture about getters and setters. Do you 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 looked at it in one of the articles earlier. Here we made a serious mistake: we opened our data, as a result of which fellow programmers had direct access to the class fields and changing their values. Moreover, these values ​​were assigned without checks, as a result of which in our program it is possible to create a cat with an age of -1000 years, a name "" and a weight of 0. To solve this problem, we used getters and setters , and also limited access to the data using a modifier private.
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) {
       // checking the input parameter
       this.name = name;
   }

   public int getAge() {
       return age;
   }

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

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       // checking the input parameter
       this.weight = weight;
   }
}
Actually, restricting access to fields and implementing getters-setters is the most common example of use privatein real work. That is, implementing encapsulation in a program is the main purpose of this modifier. This applies not only to fields, by the way. Imagine that in your program there is a method that implements some VERY complex functionality. To come up with this as an example... Let's say your method readDataFromCollider()takes an address with data as input, reads data from the Large Hadron Collider in byte format, converts this data into text, writes it to a file and prints it. Even the description of the method looks creepy, let alone the code :) To increase the readability of the code, it would be good not to write complex method logic in one place, but, on the contrary, to break the functionality into separate methods. For example, the method readByteData()is responsible for reading data, convertBytesToSymbols()converting the data read from the collider into text, saveToFile()saving the resulting text to a file, and printColliderData()printing our data file. The method readDataFromCollider()would end up being 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) {

       // convert bytes to characters
   }

   public File saveToFile(String[] colliderData) {

       // save the read data to a file
   }

   public void printColliderData(File fileWithColliderData) {

       // print data from file
   }
}
However, as you remember from the lecture on interfaces, the user only gets access to the final interface. And our 4 methods are not part of it. They are auxiliary : we created them to improve code readability and to avoid cramming four different tasks into one method. There is no need to give the user access to these methods. If a user has access to the method when working with a collider convertBytesToSymbols(), he most likely simply will not understand what this method is and why it is needed. What bytes are converted? Where did they come from? Why convert them to text? The logic that runs in this method is not part of the user interface. Only the method readDataFromCollider()is part of the interface. What to do with these four "internal" methods? Right! Restrict access to them with a modifier private. This way they can easily do their work inside the class and not confuse the user, who does not need the logic of each of them separately.
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) {
       // convert bytes to characters
   }

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

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

Modifier protected

The next most restrictive access modifier is protected. Access modifiers.  Private, protected, default, public - 3 Fields and methods designated with the access modifier protectedwill be visible:
  • within all classes that are in the same package as ours;
  • within all the successor classes of our class.
It is immediately difficult to imagine when this might be needed. Don’t be surprised: protectedthere are much fewer cases of application than private, and they are specific. Imagine that we have an abstract class AbstractSecretAgentthat denotes a secret agent of some intelligence agency, as well as a package top_secretthat contains this class and its descendants. Concrete classes - FBISecretAgent, MI6SecretAgent, MossadSecretAgentetc. - are inherited from it. Inside the abstract class we want to implement an agent counter. When a new agent object is created somewhere in the program, it will increase.
package top_secret;

public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
But our agents are secret! This means that only they and no one else should know about their number. We can easily add a modifier protectedto the field agentCount, and then either objects of other secret agent classes, or those classes that are located in our “secret” package, can get its value top_secret.
public abstract class AbstractSecretAgent {

   protected static int agentCount = 0;
}
It is for such specific tasks that a modifier is needed protected:)

package visible modifier

Next on our list is the modifier defaultor, as it is also called, package visible. It is not indicated by a keyword because it is set by default in Java for all fields and methods. If you write in your code -
int x = 10;
... the variable xwill have this same package visibleaccess. If a method (or variable) is not marked with any modifier, it is considered to be marked with the "default modifier". Variables or methods with such a modifier (i.e. without any at all) are visible to all classes of the package in which they are declared. And only to them. Its uses are limited, just like the modifier protected. Most often, default-access is used in a package where there are some utility classes that do not implement the functionality of all other classes in this package. Let's give an example. Imagine we have a " services " package. Inside it are various classes that work with the database. For example, there is a class UserServicethat reads user data from a database, a class CarServicethat reads data about cars from the same database, and other classes, each of which works with its own type of objects and reads data about them from the database.
package services;

public class UserService {
}

package services;

public class CarService {
}
However, a situation can easily happen when the data in the database is in one format, but we need it in another. Imagine that the user's date of birth in the database is stored in the format TIMESTAMP WITH TIME ZONE...
2014-04-04 20:32:59.390583+02
...we instead need the simplest object - java.util.Date. For this purpose, we can create servicesa special class inside the package Mapper. He will be responsible for converting data from the database into the Java objects we are familiar with. A simple helper class. We usually create all classes as public class ClassName, but this is not necessary. We can declare our helper class simply as class Mapper. In this case, it still does its job, but is not visible to anyone outside the package services!
package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
And this, in fact, is the correct logic: why would someone outside the package see an auxiliary class that works only with classes of the same package?

public modifier

And last on the list, but not least - the modifier public! You met him on the first day of studying at JavaRush, launching public static void main(String[] args). Access modifiers.  Private, protected, default, public - 4 Now that you have studied the lectures about interfaces, its purpose is obvious to you :) After all, publicit was created in order to give something to users. For example, the interface of your program. Let's say you wrote a translator program, and it can translate Russian text into English. You have created a method translate(String textInRussian)within which the necessary logic is implemented. You marked this method with the word public, and now it will become part of the interface:
public class Translator {

   public String translate(String textInRussian) {

       // translates text from Russian to English
   }
}
You can associate a call to this method with the “translate” button on the program screen - and that’s it! Anyone can use it. Parts of the code marked with the modifier publicare intended for the end user. To give an example from life, privatethese are all the processes occurring inside the TV when it is working, and publicthese are the buttons on the TV remote control with which the user can control it. At the same time, he does not need to know how the TV works and how it works. The remote control is a set publicof -methods: on(), off(), nextChannel(), previousChannel(), increaseVolume(), decreaseVolume()etc.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION