1. Properties: getters and setters

When a large project is being developed by dozens of programmers at the same time, problems often crop up if they handle the data stored in class fields differently.

Maybe people fail to study the class documentation in detail, or perhaps it doesn't describe every case. As a result, there are frequent situations when an object's internal data can become "corrupted", making the object invalid.

To avoid these situations, it is customary to make all class fields private in Java. Only the class's methods can modify the variables of the class. No methods from other classes can directly access the variables.

If you want other classes to be able to get or change the data inside objects of your class, you need to add two methods to your class — a get method and a set method. Example:

Code Note
class Person
{
   private String name;

   public Person(String name)
   {
      this.name = name;
   }

   public String getName()
   {
      return name;
   }

   public void setName(String name)
   {
      this.name = name;
   }
}


private name field



Initialization of the field via the constructor


getName() — This method returns the value of the name field




setName() — This method changes the value of the name field

No other class can directly change the value of the name field. If someone needs to get the value of the name field, they will have to call the getName() method on a Person object. If some code wants to change the value of the name field, it will need to call the setName() method on a Person object.

The getName() method is also called the "getter for the name field", and the setName() method is called the "setter for the name field".

This is a very common approach. In 80-90% of all Java code, you will never see public variables in a class. Instead, they will be declared private (or protected), and each variable will have public getters and setters.

This approach makes the code longer, but more reliable.

Accessing a class variable directly is like turning your car through double yellow lines: it's easier and faster, but if everyone does it, then things get worse for everyone.

Let's say you want to create a class that describes a point (x, y). Here's how a novice programmer would do it:

class Point
{
   public int x;
   public int y;
}

Here's how an experienced Java programmer would do it:

Code
class Point {
   private int x;
   private int y;

   public Point(int x, int y) {
      this.x = x;
      this.y = y;
   }

   public int getX() {
      return x;
   }

   public void setX(int x) {
      this.x = x;
   }

   public int getY() {
      return y;
   }

   public void setY(int y) {
      this.y = y;
   }
}

Is the code longer? Undoubtedly.

But you can add parameter validation to getters and setters. For example, you can make sure that x and y are always greater than zero (or not less than zero). Example:

Code Note
class Point {
   private int x;
   private int y;

   public Point(int x, int y) {
      this.x = x < 0 ? 0 : x;
      this.y = y < 0 ? 0 : y;
   }

   public int getX() {
      return x;
   }

   public void setX(int x) {
      this.x = x < 0 ?  0 : x;
   }

   public int getY() {
      return y;
   }

   public void setY(int y) {
      this.y = y < 0 ? 0 : y;
   }
}

undefined
11
Task
New Java Syntax, level 11, lesson 4
Locked
Class counter
Declare a static int variable catCount in the Cat class. Declare a constructor, i.e. public Cat(), that increases this variable by 1.
undefined
11
Task
New Java Syntax, level 11, lesson 4
Locked
Static methods: int getCatCount() and setCatCount(int)
In the Cat class, implement two static methods: int getCatCount() and setCatCount(int), which you can use to get/change the number of cats (catCount variable).

2. Object lifetime

You already know that objects are created using the new operator, but how are objects deleted? They don't exist forever. There isn't enough memory for that.

In many programming languages, such as C++, there is a special delete operator for deleting objects. But how does this work in Java?

In Java, everything is arranged a little differently. Java has no delete operator. Does this mean that objects are not deleted in Java? No, they are deleted, of course. Otherwise, Java applications would quickly run out of memory, and there wouldn't be any talk of programs running without interruption for months.

In Java, the deletion of objects is completely automated. The Java machine itself handles the deletion of objects. This process is called garbage collection, and the mechanism that collects garbage is called the garbage collector (GC).

So how does the Java machine know when to delete an object?

The garbage collector divides all objects into "reachable" and "unreachable". If there is at least one reference to an object, it is considered reachable. If there is no variable that refers to an object, the object is considered unreachable and is declared garbage, which means that it can be deleted.

In Java, you can't create a reference to an existing object — you can only assign references that you already have. If we erase all references to an object, then it is lost forever.

Circular references

That logic sounds great until we come upon a simple counterexample: suppose we have two objects that reference each other (store references to each other). No other objects store references to these objects.

These objects cannot be accessed from the code, but they are still referenced.

This is why the garbage collector divides objects into reachable and unreachable rather than "referenced" and "unreferenced".

Reachable objects

First, objects that are 100% alive are added to the reachable list. For example, the current thread (Thread.current()) or the console InputStream (System.in).

Then the list of reachable objects expands to include objects that are referenced by the initial set of reachable objects. Then it is expanded again to include objects that are referenced by this enlarged set, and so on.

That means that if there are some objects that only refer to each other, but there is no way to reach them from reachable objects, then those objects will be considered garbage and will be deleted.


3. Garbage collection

Memory fragmentation

Another important point related to object deletion is memory fragmentation. If you constantly create and delete objects, soon memory will be heavily fragmented: areas of occupied memory will be interspersed with areas of unoccupied memory.

As a result, we can easily get into a situation where we can't create a large object (for example, an array with a million elements), because there is not a large chunk of free memory. In other words, there may be free memory, even a lot of it, but there may not be a large contiguous block of free memory

Memory optimization (defragmentation)

The Java machine solves this problem in a specific way. It looks something like this:

Memory is divided into two parts. All objects are created (and deleted) in just one half of memory. When it comes time to clean up the holes in memory, all objects in the first half are copied to the second half. But they are copied right next to each other so that there are no holes.

The process looks roughly like this:

Step 1: After creating objects

Garbage collection in Java

Step 2: Appearance of "holes"

Garbage collection in Java 2

Step 3: Elimination of "holes"

Garbage collection in Java 3

And that's why you don't need to delete objects. The Java machine simply copies all reachable objects to a new location, and frees the entire area of memory where the objects used to be stored.

undefined
11
Task
New Java Syntax, level 11, lesson 4
Locked
StringHelper class
In the StringHelper class, implement two static methods: - String multiply(String s, int count) - returns a string that has been repeated count times - String multiply(String s) - returns a string that has been repeated 5 times. Example: Amigo -> AmigoAmigoAmigoAmigoAmigo
undefined
11
Task
New Java Syntax, level 11, lesson 4
Locked
Controlling body weight
The program should read a weight entered by the user in kilograms and a height in meters. Then it should display a message about the user's body mass index. Implement a static method in the Body class. The method should calculate the body mass index and display the following message: "Underweight: B
undefined
11
Task
New Java Syntax, level 11, lesson 4
Locked
ConsoleReader class
In the ConsoleReader class, implement four static methods: - String readString() - reads a string from the keyboard - int readInt() - reads a number from the keyboard - double readDouble() - reads a fractional number from the keyboard boolean readBoolean() - reads the string "true" or "false" from t
undefined
11
Task
New Java Syntax, level 11, lesson 4
Locked
Calculator
Make a Calculator class, which will have 5 static methods: int plus(int a, int b) - returns the sum of a and b int minus(int a, int b) - returns the difference between a and b int multiply(int a, int b) - returns the product of a and b double divide(int a, int b) - returns the result of dividing a b
undefined
11
Task
New Java Syntax, level 11, lesson 4
Locked
Distance between two points
Implement the static double getDistance(x1, y1, x2, y2) method. It should calculate the distance between two points. Use the double Math.sqrt(double a) method, which calculates the square root of the passed argument. The distance between points is calculated according to the formula: https://javaru