Java configures private fields inside constructors

A common design practice is to make instance variables private and have public recipients and setters to access them. But many times I saw code samples on the Internet that have constructors that assign values ​​directly to a private instance variable instead of using installers inside constructors. Did I miss something?

public class Person{ private String name; public Person(String name){ //is this right, seems like the whole encapsulation purpose is defeated this.name = name; //shouldn't this be used setName(name); } public String getName(){ return this.name; } public void setName(String name){ this.name = name; } } 
+6
source share
9 answers

You are missing nothing. What you do depends entirely on your situation. However, consider the following:

Very often you have to check the parameters in the setter. For example, suppose I have a class with a field that can contain a value from 0 to 10 (ticks are not needed for the exception type below, but I turn it on for clarity):

 public class Example { private int value; public Example () { } public final int getValue () { return value; } public final void setValue (int value) throws IllegalArgumentException { if (value < 0 || value > 10) throw new IllegalArgumentException("Value is out of range."); } } 

Here setValue () checks the "value" to make sure that it follows the rules. We have an invariant that states that "the example will not exist with the range value." Now suppose we want to create a constructor that takes a value. You can do it:

 public class Example { ... public Example (int value) { this.value = value; } ... } 

As you can see, there is a problem. The new Example (11) statement will succeed, and now there is an Example that violates our rules. However, if we use setter in the constructor, we can conveniently add all the design checks to the constructor:

 public class Example { ... public Example (int value) throws IllegalArgumentException { setValue(value); // throws if out of range } ... } 

Thus, there are many advantages to this.

Now there are still cases where you can directly assign values. Firstly, you may not have available setters (although I would argue that creating private or batch private setters as you wish, for the reasons mentioned above, is still desirable to support / bean reflection, and to simplify the verification into a more complex code).

Another reason may be that you might have a constructor that somehow knows in advance that real values ​​will be assigned, and therefore does not require verification and can directly assign variables. This is usually not a compelling reason to skip using setters.

However, in general, it is generally recommended that you use setters wherever possible; this usually leads to cleaner and more understandable codes that are easier to maintain as complexity increases.

Most of the examples that you see where people set variables directly are just people who are “lazy,” which is quite acceptable if the situation justifies this (maybe you are writing a program or application for quick verification and do not want to implement a bunch of setters, for example ) There is nothing wrong with that if you keep the big picture in your head and only "lazy" when appropriate.

Something I would like to add based on some other answers here: If you redefine the setter in a subclass and the data you specify sets the invariants that are supposed to be the base class, either the corresponding final setters should be done or the base class will not must make these assumptions. If overriding setters break invariants of the base class, then a big problem arises.

You will notice that the getter / setter is final in the example above. This is due to the fact that our rule is that "any example should have a value from 0 to 10". Therefore, this rule applies to subclasses. If we did not have this rule, and if any example could take any value, we would not need the final setter and it could override subclasses.

Hope this helps.

+5
source

Sometimes, when you want to make a class immutable, this is just one of the things you need to do. And do not set the configuration methods in this case at all.

+2
source

Depending on the context, the use of getters and setters is actually a greater encapsulation violation than the use of member variables in constructors. If you want to set the member variable "name" of this class, any of these approaches will work, since the construct is hidden from the caller and thus does not break encapsulation. One warning is that using setName inside the constructor may call an overridden method in the subclass, which may not be what you want (since it can leave the name undefined in the superclass).

Here is a similar question that may provide further information:

calling setters from the constructor

+2
source

Setting variables to private is an encouragement to encapsulation from other classes.

If setName(String) not intended to do something extra (which does not imply the name of the method), there is no need to use the installer when you are in a class with a private variable.

0
source

This does not cancel the encapsulation, as the private member is still hidden from other classes

If the modifier method does not contain any logic and simply sets the member, then there is no difference between directly setting the member to call its setter method, although a setter should be called for best practice.

The installer indicates that the name of this person may change in the future and makes it easy without creating the entire object of the object.

0
source

private variables are available directly anywhere in the class

setting private variables is to encapsulate them from other classes

0
source

Initializing variables inside the constructor is a very common practice. It can be used to assign values ​​to variables based on which the user of the constructor called. You cannot write code based on the assumption that client code will call the setter method to assign value to instance variables. It is always safe to assign a default value to a variable when its object is created (i.e. Inside the constructor).

There is a difference between initializing variables inside the constructor and setting it to a different value in accordance with the requirement of the calling code (using the setter method). Both have different goals and different goals.

0
source

This is completely normal. Some variables may need to be initialized as soon as the object is created, so it makes sense to pass them in the constructor, and many times we do not want to provide setters for these variables in order to avoid changing the values ​​after creating the object.

0
source

With it, you can directly assign values ​​to the class set by setter; it does not perform any other processing.

Basically, installers / getters are used to provide restrictive access to sensitive data, such as returning a copy of data instead of referencing a private object, checking data in a getter, etc.

Since the constructor is part of the object itself, and we are sure that we are doing it right, then its good.

0
source

Source: https://habr.com/ru/post/950969/


All Articles