Зачем нужны геттеры и сеттеры java
Перейти к содержимому

Зачем нужны геттеры и сеттеры java

  • автор:

Для чего используются геттеры и сеттеры в Java?

Добрый день! Подскажите, пожалуйста, новичку, для чего используются сеттеры и геттеры в Java?

Суть я понимаю, что они позволяют получать доступ к переменным других классов с уровнем доступа private, но зачем тогда ставить уровень доступа private на переменные, если все равно через геттеры и сеттеры можно их считать из другого класса.

P.S. Сильно не ругайте, только начал осваивать Java.

  • Вопрос задан более двух лет назад
  • 562 просмотра

Простой 1 комментарий

  • Facebook
  • Вконтакте
  • Twitter
  • Facebook
  • Вконтакте
  • Twitter

Maksclub

Maksclub

Нет никакого смысла, если нормально программировать и строить простой удобный код. Этакий способ формально соблюсти инкапсуляцию и сокрытие данных: состояние приватное? Приватное 🙂

Чреваты тем, что плодят высокую связанность в коде, состояние и управляется снаружи (на основе геттеров) и контролируются инварианты где угодно и как угодно. По сути превращаем сущности в структуры, но тк это все же бизнес-объекты, а знания бизнес-состояния нужно — то они гуляют по всему проекту и ничем не ограничены. заплетая и заплетая код снова и снова, а также погружая в эти «сущности» все больше и больше знаний.
Доходит до того, что через заказ можно достать товар, через товар можно достать поставщика, через поставщика пользователя с данными аутентификации. и все работает со всем. плодя кучу сервисов и взрывая мозг.

Нужны только бля быстрых CRUD и для совместимости с кучей библиотек. А также говнокодерам «использовать данные в сервисах»

Сеттеры и геттеры нужны для разных манипуляций: валидация, костыльного маппинга, сериализации и десерриализации.

Хорошими и современной практикой сейчас является — не использование и геттеров и сеттеров.

Мои изыскания:
Зачем (не)нужны геттеры?
Геттеры/сеттеры и проблема с инкапсуляцией (примеры на Symfony, аналог Spring в php с аналогичной плохой практикой)

Зачем нужны геттеры и сеттеры java

Getter and Setter are methods used to protect your data and make your code more secure. Getter returns the value (accessors), it returns the value of data type int, String, double, float, etc. For the program’s convenience, getter starts with the word “get” followed by the variable name.

While Setter sets or updates the value (mutators). It sets the value for any variable used in a class’s programs. and starts with the word “set” followed by the variable name. Getter and Setter make the programmer convenient in setting and getting the value for a particular data type. In both getter and setter, the first letter of the variable should be capital.

Java Getter and Setter Tutorial — from Basics to Best Practices

The following code is an example of simple class with a private variable and a couple of getter/setter methods:

The class declares a private variable, number . Since number is private, code from outside this class cannot access the variable directly, like this:

Instead, the outside code have to invoke the getter, getNumber() and the setter, setNumber() in order to read or update the variable, for example:

So, a setter is a method that updates value of a variable. And a getter is a method that reads value of a variable.

2. Why getter and setter?

That ensures the value of number is always set between 10 and 100. Suppose the variable number can be updated directly, the caller can set any arbitrary value to it:

And that violates the constraint for values ranging from 10 to 100 for that variable. Of course we don’t expect that happens. Thus hiding the variable number as private and using a setter comes to rescue.

On the other hand, a getter method is the only way for the outside world reads the variable’s value:

The following picture illustrates the situation:

getter and setter

So far, setter and getter methods protect a variable’s value from unexpected changes by outside world — the caller code.

When a variable is hidden by private modifier and can be accessed only through getter and setter, it is encapsulated. Encapsulation is one of the fundamental principles in object-oriented programming (OOP), thus implementing getter and setter is one of ways to enforce encapsulation in program’s code.

Some frameworks such as Hiberate, Spring, Struts… can inspect information or inject their utility code through getter and setter. So providing getter and setter is necessary when integrating your code with such frameworks.

3. Naming convention for getter and setter

getXXX() and setXXX()

where XXX is name of the variable. For example with the following variable name:

then the appropriate setter and getter will be:

If the variable is of type boolean , then the getter’s name can be either isXXX() or getXXX() , but the former naming is preferred. For example:

The following table shows some examples of getters and setters which are qualified for naming convention:

Variable declaration

Getter method

Setter method

void setQuantity(int qty)

void setFirstName(String fname)

void setBirthday(Date bornDate)

void setRich(Boolean rich)

4. Common mistakes when implementing getter and setter

Mistake #1: Have setter and getter, but the variable is declared in less restricted scope.

The variable firstName is declared as public, so it can be accessed using dot (.) operator directly, making the setter and getter useless. Workaround for this case is using more restricted access modifier such as protected and private:

In the book Effective Java, Joshua Bloch points out this problem in the item 14: In public classes, use accessor methods, not public fields.

Mistake #2: Assign object reference directly in setter

And following is code that demonstrates the problem:

An array of integer numbers myScores is initialized with 6 values (line 1) and the array is passed to the setScores() method (line 2). The method displayScores() simply prints out all scores from the array:

Line 3 will produce the following output:

That are exactly all elements of the myScores array.

Now at line 4, we can modify the value of the 2 nd element in the myScores array as follow:

What will happen if we call the method displayScores() again at line 5? Well, it will produce the following output:

You can realize that the value of 2 nd element is changed from 5 to 1, as a result of the assignment in line 4. Why does it matter? Well, that means the data can be modified outside scope of the setter method which breaks encapsulation purpose of the setter. And why that happens? Let’s look at the setScores() method again:

The member variable scores is assigned to the method’s parameter variable scr directly. That means both the variables are referring the same object in memory — the myScores array object. So changes made to either scores variable or myScores variable are actually made on the same object.

Workaround for this situation is to copy elements from scr array to scores array, one by one. The modified version of the setter would be like this:

What’s difference? Well, the member variable scores is no longer referring to the object referred by scr variable. Instead, the array scores is initialized to a new one with size equals to the size of the array sc r . Then we copy all elements from the array scr to the array scores , using System.arraycopy() method.

Run the example again and it will give the following output:

Now the two invocation of displayScores() produce the same output. That means the array scores is independent and different than the array scr passed into the setter, thus the assignment:

does not affect the array scores .

So, the rule of thumb is, if you pass an object reference into a setter method, then don’t copy that reference into the internal variable directly. Instead, you should find some ways to copy values of the passed object into the internal object, like we have copied elements from one array to another using System.arraycopy() method.

Mistake #3: Return object reference directly in getter

And the following code snippet:

it will produce the following output:

As you notice, the 2 nd element of the array scores is modified outside the setter, at line 5. Because the getter method returns reference of the internal variable scores directly, so the outside code can obtain this reference and makes change to the internal object.

Workaround for this case is that, instead of returning the reference directly in the getter, we should return a copy of the object, so the outside code can obtain only a copy, not the internal object. Therefore we modify the above getter as follows:

So the rule of thumb is: do not return reference of the original object in getter method. Instead, it should return a copy of the original object.

5. Implementing getters and setters for primitive types

For example, the following code is safe because the setter and getter involve in a primitive type of float:

So, for primitive types, there is no special trick to correctly implement the getter and setter.

6. Implementing getters and setters for common object types

Getters and Setters for String objects

Getters and Setters for Date objects

The clone() method returns an Object , so we must cast it to Date type.

You can learn more about this in the item 39: Make defensive copies when needed in this well-known Java book.

7. Implementing getters and setters for collection type

Consider the following program:

According to the rules for implementing getter and setter, the three System.out.println() statements should produce the same result. However, when running the above program it produces the following output:

That means the collection can be modified from code outside of the getter and setter.

For a collection of Strings, one solution is to use the constructor that takes another collection as argument, for example we can change code of the above getter and setter as follows:

Re-compile and run the CollectionGetterSetter program, it will produce desired output:

NOTE: The constructor approach above is only working with collections of Strings, but it will not work for collections objects. Consider the following example for a collection of Person object:

It produces the following output when running:

Because unlike String which new objects will be created whenever a String object is copied, other Object types are not. Only references are copied, so that’s why two collections are distinct but they contain same objects. In other words, it is because we haven’t provided any mean for copying objects.

Look at the collection API we found that ArrayList , HashMap , HashSet , … implement their own clone() methods, these methods return shallow copies which do not copy elements from the source collection to the destination. According to Javadoc of the clone() method of ArrayList class:

Thus we cannot use the clone() method of these collection classes. The solution is to implement the clone() method for our own defined object – the Person class in the above example. We implement the clone() method in the Person class as follows:

The setter for listPeople is modified as follows:

The corresponding getter is modified as follows:

That results in a new version of the class CollectionGetterSetterObject as follows:

Compile and run the new version of CollectionGetterSetterObject , it will produce the desired output:

So key points for implementing getter and setter for collection type are:

  • For collection of String objects: does not need any special tweak since String objects are immutable.
  • For collection of custom types of object:
    • Implement clone() method for the custom type.
    • For the setter, add cloned items from source collection to the destination one.
    • For the getter, create a new collection which is being returned. Add cloned items from the original collection to the new one.

    8. Implementing getters and setters for your own type

    As we can see, the class Person implements its clone() method to return a cloned version of itself. Then the setter method should be implemented as follows:

    And for the getter method:

    So the rules for implementing getter and setter for a custom object type are:

    • Implement clone() method for the custom type.
    • Return a cloned object from the getter.
    • Assign a cloned object in the setter.

    Other Java Coding Tutorials:

    About the Author:

    Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook and watch his Java videos you YouTube.

    Add comment
    Comments

    I wish you had an example where you actually invoked an accessor!
    for example you often use the accessor

    Getters and Setters in Java Explained

    Getters and Setters in Java Explained

    Getters and setters are used to protect your data, particularly when creating classes.

    For each instance variable, a getter method returns its value while a setter method sets or updates its value. Given this, getters and setters are also known as accessors and mutators, respectively.

    By convention, getters start with the word «get» and setters with the word «set», followed by a variable name. In both cases the first letter of the variable’s name is capitalized:

    The getter method returns the value of the attribute. The setter method takes a parameter and assigns it to the attribute.

    Once the getter and setter have been defined, we use it in our main:

    Getters and setters allow control over the values. You may validate the given value in the setter before actually setting the value.

    Why use getters and setters?

    Getters and setters allow you to control how important variables are accessed and updated in your code. For example, consider this setter method:

    By using the setNumber method, you can be sure the value of number is always between 1 and 10. This is much better than updating the number variable directly:

    If you update number directly, it’s possible that you’ll cause unintended side effects somewhere else in your code. Here, setting number to 13 violates the 1 to 10 constraint we want to establish.

    Making number a private variable and using the setNumber method would prevent this from happening.

    On the other hand, the only way to read the value of number is by using a getter method:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *