Should I use the Java public variable?
In school, I've been told many times to stop using public for my variables. I haven't asked why yet.
This question: Are Java's public fields just a tragic historical design flaw at this point? seems kinda related to this. However, they don't seem to discuss why it is "wrong", but instead focus on how they can use them instead.
Look at this (unfinished) class:
public class Reporte {
public String rutaOriginal;
public String rutaNueva;
public int bytes Originales;
public int bytesFinales;
public float ganancia;
/**
* Constructor para objetos de la clase Reporte
*/
public Reporte() {
}
}
No need to understand Spanish. All this class does is hold some statistics (those public fields) and then do some operations with them (later).
I will also need to be modifying those variables often. But well, since I've been told not to use public, this is what I ended up doing:
public class Reporte {
private String rutaOriginal;
private String rutaNueva;
private int bytes Originales;
private int bytesFinales;
private float ganancia;
/**
* Constructor para objetos de la clase Reporte
*/
public Reporte() {
}
public String getData Original() {
return rutaOriginal;
}
public String getRutaNueva() {
return rutaNueva;
}
public int getBytesOriginales() {
return bytes Originales;
}
public int getBytesFinales() {
return bytesFinales;
}
public float getGanancia() {
return ganancia;
}
public void setRutaOriginal(String rutaOriginal) {
this.rutaOriginal = rutaOriginal;
}
public void setRutaNueva(String rutaNueva) {
this.ruta Nueva = ruta Nueva;
}
public void setBytesOriginales(int bytesOriginales) {
this.bytes Originales = bytes Originales;
}
public void setBytesFinales(int bytesFinales) {
this.bytesFinales = bytesFinales;
}
public void setGanancia(float ganancia) {
this.ganancia = ganancia;
}
}
Looks kinda pretty. But it seems like a waste of time.
Google searches about "When to use public in Java" and "Why shouldn't I use public in Java" seem to discuss a concept of mutability, although I'm not really sure how to interpret such discussions. I do want my class to be mutable - all the time.
Java public variable breaks encapsulation - the core principle here is that the fields of your class are implementation details, by exposing it as a public field, you are telling everything outside that class that it is an actual piece of data that is stored by the class - something external classes don't need to know, they just need to be able to get or set that piece of data. As soon as you make something public, external classes should be able to depend on it, and it should not change often, by implementing as a method, you are retaining the flexibility to change the implementation at a later point without affecting users of the class.
If you wanted to change one of the fields so it's calculated, or retrieved from a service when it's called, you wouldn't be able to without breaking other parts of your application. Other reasons are that it allows you to control access to the variable (i.e. make it immutable as you already highlighted). In setters you can also add checking code, and you can add behaviours to getters and setters that do other things when a variable is get or set (though this may not always be a good thing). You can also override a method in a derived class, you can't override a field.
There are some very rare situations where it is better to have public field instead of a method - but this really only applies in very high performance applications (3D games & financial trading applications), unless you are writing one of these, avoid public fields - and if you do care about performance to that level, Java is probably not the best choice anyway.
Just a note on mutability - in general you should try to make things immutable until you have a genuine reason to make them mutable - the less your code exposes in its public API, the easier it is for long term maintenance, and in a multi-threaded situation, immutable objects are thread safe, mutable objects need to implement locking.