Why use get and set in Java?

20

I learned in college a while ago that I should always use getters and setters to access values in an object and I heard it is for security. p>

So I ended up always using and seeing other people using, until I started programming Android and I noticed that Google says to NOT use it for perfomance issues (Android only).

So what is get and set serving? Is it only by good practice? I did not understand why good practices in this case. What influences do I use or not?

Is the security question true? It seems to me kind of unreasonable to say this.

Example:

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

pessoa.nome; //acessando uma variavel publica diretamente
    
asked by anonymous 14.11.2014 / 05:55

3 answers

19

"Security" in this case refers only to a programmer accidentally accessing a variable in a way different from 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 must always remember that denominador can not be zero. But what if you forget? In time, nothing will happen ... But later, when another part of the code calls calcular , it will give a division error by zero. In an hour you are not expecting, and it will look like it was the call to the calculation that caused the exception (making it harder to debug).

Now, let's 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 this case, you continue having to remember that you can not pass zero, but what if you forget, what changes? It changes that the exception will be thrown immediately when trying to assign the value, pointing to the exact line of code where the error occurred, so it is much easier to identify and correct the error.

Note that in the case of numerador , it does not make sense to create getter and setter , you can either do it (by convention) or not. >

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

In general the loss of performance in using one more method is paltry to the benefits that this technique brings. However, if you are always creating getters and setters "because I have learned that this is how it should be", but never or rarely need to validate a field, or refactor the implementation, or you have no one but yourself consuming your API, then the thing changes shape: not only do you spend more time writing a bunch of useless code, but the small losses in performance over the entire project pile up, (I doubt it, it looks like micro-optimization, but you'll know ... maybe Android's Java is not as optimized to handle this as the official JVM).

I think that's the reason behind this recommendation not to use on Android. Is the code "less secure"? Stay. But it's just a matter of being more careful when programming (and this is always "good practice"). Regarding the final product, this in itself does not cause any vulnerability in the code or anything like that.

    
14.11.2014 / 10:39
8

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

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

    public Ponto(){}

   // métodos da classe.
}

From the moment 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 using "private" instead of "public". Soon thereafter comes the adorable gets and sets. With the use of gets and sets, you allow a private visibility variable to be accessed. Let's take 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 example above, only through the getX and setX methods you can manipulate the variable X, whereas the variable Y does not have get and set can not be accessed directly. Now the most important part. It does not make sense to create classes with private visibility variables if you are going to create all (variables) get and set . Time, if the goal of private is to disable access, what sense does it use get and set if they give direct access to the variable? But why do we actually use it? simple, by standardization, but we should use it moderately. For the reasons already mentioned.

Hug.

    
14.11.2014 / 07:09
7

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

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 does not give any security. If performance is considered, it is because your execution stack gets a higher level to handle the value of the variable age.

Another security consideration is that there is a programming technique called Reflection . I leave it to you to research about this, but in a nutshell: making a private variable does not mean that it can not 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 some logic that is of interest to you. For example, assuming you have a property by reference, such as a list. Let's give our class a list of children:

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

If you attempt to access this property in an instance, you may receive a 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 accessory. Let's have the courtesy to assure the user of our API that he will be able to access a guaranteed list instantiated, like this:

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 required to read or write values for the class gets encapsulated in them.

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

    
14.11.2014 / 14:36