Why use get and set in Java?

Asked

Viewed 5,317 times

21

I learned in college a while back that you should always use getters and setters for access of values in an object and I heard that it is for security reasons.

So I ended up always using and seeing other people using, until I started programming Android and noticed that Google says to NAY use, for performance reasons (only in the case of Android).

So what’s the point get and set? Is it just good practice? I don’t understand why good practice in this case. What influences whether I use it or not?

Is the question of security true? It seems to me rather illogical to say this.

Example:

pessoa.getNome(); //acessando uma variavel privada com get

pessoa.nome; //acessando uma variavel publica diretamente
  • 4

    Could you post a link where this information says "Google says not to use, for reasons of performance (only in the case of Android)"? sff (ATTENTION is just curiosity)

  • 3

    Check out this link, address in general the concept of encapsulation/security http://www.guj.com.br/java/104592-heranca#564414 reply to @vinigody

  • 7
  • 3

    If it weren’t for Google diz para NÃO usar, por questões de perfomance (somente no caso do Android), I’d say it’s duplicate. As @jsantos1991 said, you could tell us where you got this information from?

  • 2

    This one in an article on performance tips http://developer.android.com/training/articles/perf-tips.html It seems to me that proguard eliminates these methods when generating apk

3 answers

20


"Security" in this case refers only to a programmer accidentally accessing a variable in a way other than that intended by the class author (not necessarily a different programmer). Let me give you an example:

class Fração {
    int numerador;
    int denominador; // Não pode ser zero

    public int calcular() { return numerador / denominador; }
}

If you can access the variables directly, you need to always remember that denominador can’t be zero. But what if you forget? At the time, nothing will happen... But later, when another part of the code calls calcular, He’s gonna make a division error by zero. At a time you are not waiting, and it will seem that it was the call to calculus that caused the exception (making it more difficult to debug).

Now, say you change the visibility of this variable to private and create a getter and a Setter:

class Fração {
    int numerador;
    private int denominador; // Não pode ser zero

    public int getDenominador() {
        return denominador;
    }

    public void setDenominador(int denominador) {
        if ( denominador == 0 )
            throw new IllegalArgumentException("O denominador não pode ser zero!");
        this.denominador = denominador;
    }

    public int calcular() { return numerador / denominador; }
}

In that case, you continues But if you forget, what changes? Changes that the exception will be thrown immediately when trying to assign the value by pointing to the exact line of code where the error occurred, so that it is much easier to identify and correct the error.

Note that in the case of numerador, it makes no sense to create getter and Setter, you can do it (by convention) or not.

There are other benefits to having an extra abstraction layer around your variables, for example allowing you to change the internal representation of your class while keeping your contract constant. These benefits are most significant when you want to have a stable API, or when you program on a large team where not everyone knows exactly what each other’s code does.

In general, the loss of performance in using an extra method is derisory compared to the benefits that this technique brings. However, if you are always creating getters and setters "because I’ve learned that this is how it has to be, "but you never or rarely need to validate a field, or refactor the implementation, or you have no one but yourself consuming your API, then the picture changes: not only do you spend more time writing a bunch of useless code, how small losses in performance throughout the project accumulate, and can make a significant difference (I doubt, it seems to me micro-optimization, but you’ll know... maybe the Android Java is not as optimized to deal with this case as the official JVM).

I believe this is the reason behind this recommendation not to use on Android. Is the code "less secure"? It is. But it’s just a matter of being more careful when programming (and this is always "good practice"). In relation to the final product, this alone does not cause any vulnerability in the code or anything of that kind.

  • 2

    So there’s a big mistake while security, I heard in college that security is about hacking, and I read in articles that’s also why, so I said it’s illogical, because I couldn’t find a logic to implement this for security against hacker attacks. As for performance, worse that makes a difference, I performed the tests and when there are many calls of various gets, the performance drops dramatically, compared to not using! (on android)

  • 1

    It actually makes a lot of sense when there’s some kind of validation. I learned that should always use, and starting to study Android I saw that there was something wrong in this always. You said on a big team, it would be nice to use, but wouldn’t this be worse? Taking into account that maintenance is higher and can generate errors when using gets and sets? (disregarding the validations... Using only to return and set simple values)

  • 1

    @Felipe.rce I’m not the best person to answer this, because I’ve always worked in small teams, I don’t have practical experience developing large systems. What I do know is that the bigger the team the more important the robustness of the code and a stable API, 1º to avoid the code of one causing errors in the code of the other, 2º so you have the freedom to change your code without breaking the code of everyone in the team. If your attribute was Foo but you thought it best to use Bar, you can change the property to Bar but keep the methods as they are - making the conversion in (g/s)etter.

  • 1

    This is an example theoretical how getters and setters help keep an API stable, but again, I don’t have enough experience to corroborate or disprove that. I remember that in the libraries of Java itself there were some examples of this, I will look for and if I find update here.

  • 1

    It’s not exactly the same thing, but look for example the class Date: when it was conceived, it had several [conceptual] attributes that could be consulted and editable, such as minutes, hours, month, etc. It didn’t take long (1.1!) to notice that this was bad - given the variety of time zones or even different calendars of the Gregorian. The getters and setters could not be removed, so they were marked as obsolete (deprecated) and adapted to the new implementation, but maintained until today.

10

The use of get and set methods is practiced for safety reasons. The method applied in this case is encapsulation. The goal in fact is to not allow variables to be modified directly. For example, let’s imagine the possible class structure below:

public class Ponto {
    public int x;
    public int y;

    public Ponto(){}

   // métodos da classe.
}

Once the Point object is instantiated, you have direct access to the variables x and y. The most common thing to do in these cases is to change the visibility of the variable, usually "private" is used instead of "public". Next comes the adorable gets and sets. With the use of the gets and sets you now allow a private visibility variable to be accessed. Let’s go to another example:

public class Ponto {
    private int x;
    private int y;

    public Ponto(){}

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

    public int getX(){
       return this.x;
    }


   // métodos da classe.
}

In the above example, only through the getx and setx methods it is possible to manipulate the variable X, while the variable Y because it does not have get and set cannot be accessed directly. Now for the most important part. It makes no sense to create classes with private visibility variables if you will create for all of them (variables) the get and set. Time, if the private objective is to make access impossible, what is the point of using get and set if they give direct access to variable? But why do we actually use? simple, by standardization, but we should use it moderately. For the reasons already mentioned.

Hug.

  • So I don’t understand security reasons, since what you just mentioned in bold... If Google says it is not to use on Android, then it would be less safe? This is strange, I’m still confused... Another problem would be if the class had many variables, generating several lines of gets and sets and giving work for maintenance

  • @Felipe.rce read the other answer. Although this is not technically wrong she is a little confused and deep down does not explain what you asked.

  • 2

    "It makes no sense to create classes with private visibility variables if you will create for them all the get and set." Like?

7

Being short and thick... If all your accessor get does is return a class field, and all your accessor set does is change the value of this field, like this:

public class Pessoa {
    private int _idade;

    public int getIdade() { return _idade; }
    public void setIdade(value) { _idade = value; }
}

...Maybe you should make your field public.

That doesn’t give any security. If there is performance consideration, it is because your stack runs a higher level to manipulate the value of the variable age.

Another consideration on security is that there is a programming technique called Reflection. I leave it to you to research about it, but in a nutshell: making a variable private does not mean that it cannot be read or changed directly by other classes. You just made these operations more expensive in terms of processing.

Accessors are methods and as such serve to execute any logic that is of interest to you. For example, suppose you have a property by reference, as a list. Let’s give our person class a list of children:

public class Pessoa {
    public List<Pessoa> filhos;
}

If you try to access this property in an instance, you may get null pointer error.

Pessoa p = new Pessoa();
p.filhos.Add(new Pessoa()); // você acessou uma variável nula.

Now let’s make a really useful accessor. We courtesy to assure the user of our API that he will be able to access a guaranteed instantiated list, thus:

public class Pessoa {
    private List<Pessoa> _filhos;
    public List<Pessoa> getFilhos() {
        if (this._filhos == null) {
            this._filhos = new List<Pessoa>();
        }
        return this._filhos;
    }
}

Now this will never give null pointer error:

Pessoa p = new Pessoa();
p.getFilhos.Add(new Pessoa());

The idea behind the accessors is this: a series of operations needed to read or write values for the class is encapsulated in them.

The security of the accessors, therefore, depends on what is implemented in them. In cases like the example I used, the safety is in avoiding a null pointer exception. Other security aspects may involve checking permissions, preventing divisions by zero, ensuring that access to files will not cause lock in those files etc.

  • 4

    +1 I agree with everything, but would like to add that direct access via reflection is subject to the security policies of the JVM (via SecurityManager). For example, call obj.getClass().getDeclaredField(nomeDoAtributoPrivado) can launch a SecurityException. That is, in certain circumstances the private really prevents their access by other classes. Although, to my knowledge, most Java codes do not enable these security restrictions, except Applets (does this still exist? rsrs).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.