Java programmer expert
Many programmers, especially those who started with object-oriented programming, e.g. in Java, have a hard time understanding why it is necessary to use Encapsulation when it is not necessary at all and somehow it works without it. They mistakenly believe that it is basically just about hiding data from the outside world. I confess that I was in a similar category of people when I was learning to program in Java many years ago.

V článku sa dozvieš:
The aim of this article is to explain what encapsulation is, why to start using it, what benefits it brings and what is the relationship between encapsulation and abstraction.
Encapsulation is a way of combining member variables (i.e., data) and behavior (methods) into a single entity, which can be a class, interface, enum, etc. This encapsulation ensures that the data is not directly accessible, and the same restrictions can apply to the behavior methods that work with the data.
This is best illustrated by an example where it is a kind of capsule (similar to a pill) that contains data methods and the encapsulation is a wrapper or layer that protects them from the outside world. However, it provides a well-defined public interface to access and manipulate this object.
Encapsulation also takes care of the fact that we cannot see inside the capsule and therefore from the perspective of an external observer or user we do not know how what was implemented.
Encapsulation can be thought of as the bundling of methods and members into a capsule.

In Java, encapsulation is implemented through access modifiers such as private, public, and protected, which control the visibility of class members such as fields and methods. Private members can only be accessed within the same class, whereas public members can be accessed from anywhere in the program. Protected members can be accessed within the same class, subclasses, and classes in the same package.
Using public access get methods we can get the values stored in the class members and using set methods we can modify them and thus overwrite the old value by inserting a new one.
However, many programmers see this as just data hiding and are confused as to why we don’t just define every variable in the class as public and save writing code for the get and set methods.
Example:
If we have a Person class and a variable name of type String and an age that is of type int, we could write and use it (write and read values) like this without encapsulation:
public class Osoba {
public String meno;
public int vek;
}
Osoba osoba = new Osoba();
osoba.meno = "Dominika";
osoba.vek = 25;
System.out.println("Meno: " + osoba.meno);
System.out.println("Vek: " + osoba.vek);
If we wanted to encapsulate a similar class, we would have to hide the data members, i.e. change the access modifiers to e.g. private or protected. In that case, however, we would need at least get methods for reading, and possibly set methods for writing. The whole declaration of the class will be stretched:
public class Osoba {
private String meno;
private int vek;
public String getMeno() {
return meno;
}
public void setMeno(String meno) {
this.meno = meno;
}
public int getVek() {
return vek;
}
public void setVek(int vek) {
this.vek = vek;
}
}
Osoba osoba = new Osoba();
osoba.setMeno("Dominika");
osoba.setVek(25);
System.out.println("Meno: " + osoba.getMeno());
System.out.println("Vek: " + osoba.getVek());
So looking at the amount of code for either approach, the question of why we don’t actually define everything public and get rid of the need to define get and set methods starts to make sense.
But suppose an inattentive or malicious user enters the following as the age:
person.age = -25;
Logically, age cannot be negative, but the program does not know this. It respects all allowed range values for the int data type, so even negative values. Setting the data without any check then usually leads to errors in the program. With the second approach, however, we can modify the set method so that the age must be a positive number.
public void setVek(int vek) {
if (vek >= 0) {
this.vek = vek;
}
}
Similarly, we would be able to check the string value for the name given by the user.
public void setMeno(String meno) {
if(meno == null || meno.equals("")) {
throw new IllegalArgumentException("Meno musi obsahovat aspon 1 znak!");
}
this.meno = meno;
}
There are many good reasons to consider using accessors instead of directly accessing class fields, let’s take a look at some of them:
To properly encapsulate our class, it doesn’t mean that every data member must automatically contain a get and set method. We add those as needed. If the class will mainly execute functional code or work with immutable objects, it will have different accessor methods defined than if it worked with stateful, mutable objects.
Although novice programmers may be discouraged by writing multiple lines of code, it is certainly necessary to get used to encapsulation and the use of accessor methods. Nowadays many programming environments and editors offer support for generating get/set methods (either in the IDE or as free add-ons), which reduces the impact of this problem to some extent.
If we aim to write purely immutable data classes, using Java Records, which we covered in the last article, this is very easy to do.
V objektovom svete skrytie dát pred vonkajším svetom nie je zapuzdrenie, ale len jeho nevyhnutná časť. To znamená, že encapsulation nie je len o definovaní prístupových a mutačných metód pre triedu, ale je to širší koncept v objektovo-orientovanom programovaní, ktorý spočíva v minimalizovaní vzájomnej závislosti medzi triedami a obvykle sa realizuje prostredníctvom skrývania informácií. Správne zapuzdrený objekt zapuzdruje stav a algoritmy na manipuláciu s týmto stavom. Dôležité je ale zdôrazniť, že stav má byť zapuzdrený a manipulovaný iba algoritmami poskytnutými samotným objektom.
The beauty of encapsulation is the ability to change things without affecting users, so the goal is not to hide the data itself, but the implementation details of how that data is manipulated.
The main idea behind encapsulation is to provide a public interface through which the user can access this data. Later, we may need to change the internal representation of the data without affecting the users of the existing interface.
However, if we expose the data itself, we jeopardize the encapsulation and thus the ability to change the way the data is manipulated, we create a dependency on the data itself and not on the public interface of the class, which is bound to cause big problems sooner or later.
In Java, we can hide entire classes, thus hiding the implementation details of the entire API. For example, the Arrays.asList() method returns an implementation of the List interface, but we don’t care which particular implementation it is as long as it satisfies (implements) the List interface, right? The implementation can be changed in the future without affecting the users of this method, but the user probably won’t notice.
To better understand the concept of encapsulation, it is helpful to first understand the abstraction. Let us take an ordinary car as an example. A car consists of a number of components, much like a program. It has several subsystems such as transmission, brakes, fuel system, etc.
We know that all cars have a steering wheel through which we control the direction, they have a pedal which, when pressed, accelerates the car and another which, when pressed, stops the car. Then there is the gear lever, which allows us to control whether we are going forward or reversing. These functions form the public interface of the car abstraction. We treat all the cars in the world through this public interface of their abstraction in the same way. We can drive one car in the morning and then get out of it and drive another car in the afternoon as if it were the same car.
However, few of us know the details of how all these features are implemented under the hood. One day we may buy an electric car that has got rid of a lot of the under-the-hood components, but the control system (i.e. the public interface) has remained the same, and therefore we will be able to drive it almost immediately. However, if, for example, the steering wheel is replaced by the voice control of a self-driving car (we have changed the established interface), we will first have to relearn how to use the new car.
As can be seen in this example, the goal of encapsulation is to minimize dependency and facilitate change. We maximize encapsulation by minimizing the exposure of implementation details to the user. Class state should only be accessible through the public interface.
Security: encapsulation helps secure the code by ensuring that other entities (classes, interfaces, etc.) do not have direct access to the data.
Flexibility: encapsulation makes the code more flexible, which in turn allows the programmer to easily change or update the code.
Control: Encapsulation provides control over the data stored in member variables.
Reusability: the encapsulated code or unit can be reused anywhere in the application or in completely different programs, without having to write the code over again. Virtually all libraries work this way.
Sustainability: encapsulated components are easy to maintain because we can easily find or change things.
Encapsulation is a fundamental concept of object-oriented languages that involves combining data and methods together and controlling access to them. It makes use of data hiding, which focuses specifically on restricting direct access to certain data or methods. It also makes use of an abstraction layer that offers a public interface to the user without the need to know the internal state of the capsule – encapsulation.
If you’re a Java developer looking for a job, check out our employee benefits and respond to our job offers!
Related articles