Is there really any actual use for private variables and specific moments where they would be your only possible option? Or can you just set all of your variables as public without any actual changes to the program? It seems like a pointless practice that doesn't really change much, from my perspective, so I'm wondering if I'm overlooking something.
-
2You are overlooking [encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)). – Nick Alexeev Sep 21 '18 at 16:46
-
2Don't get discouraged by the downvotes, here they are just a way for the community to give feedback on the quality of the question, and on the fact that similar questions have been answered before, so follow the links provided in the comments above (and even the links you'll find there), and you'll get a whole bunch of answers. But let me put them in context - see my answer below. – Filip Milovanović Sep 21 '18 at 18:08
1 Answers
This has been asked many times before, so follow the links provided in the comment section under your quesion, and you'll get a whole bunch of answers. But let me put them in context.
If (1) people could write even a slightly complex piece of software perfectly on the first go, and if (2) the code is never ever going to change, then private variables are pointless. But (1) && (2) together are practically never the case in the real world. To write code that can be changed and maintained, you need to control the interdependencies between different pars of it, so that you can change each part in a way that requires no changes, or minimal changes to the other parts. One of the way to do this is to hide the implementation details of interacting classes. This is called encapsulation, and that's why you have private members. However, the point is not to make these members private and then expose them anyway with corresponding getters and setters. This 1-to-1 mapping between members and getters has little utility (yeah, there are some benefits, there is some level of encapsulation, but that's not how you do it, even though that's how you'll see it described in programming courses). What you do is you provide a set of member functions (methods) that exposes very little (if anything) about the internal structure of the class to the outside world (the other classes that call this code). These methods are formulated so that the external code doesn't ask the class for its internal data in order to do something with that data, but instead asks the class to complete some task for it. This then enables you to completely change the implementation of the class without affecting the external code at all, as long as you don't change the signature of the "outward facing" functions. And if your class implements a Java interface, and the external logic is coded against that interface, you can even swap the class for another completely (even at runtime).
Consider this (fairly contrived) example:
class Main {
public static void main(String[] args) {
Grower1 g1 = new Grower1();
g1.value += 1; // must change
if (g1.value < 10) { // must change
System.out.println(g1.value); // prints out: 1
}
Grower2 g2 = new Grower2();
g2.grow();
if (g2.getValue() < 10) { // must change
System.out.println(g2.getValue()); // prints out: 1
}
Grower3 g3 = new Grower3();
g3.grow();
if (g3.isAlive()) {
System.out.println(g3.toString()); // prints out: 1
}
}
}
class Grower1 {
public int value = 0;
}
class Grower2 {
private int value = 0;
public int getValue() {
return this.value;
}
public void grow() {
this.value += 1;
}
}
class Grower3 {
private int value = 0;
public void grow() {
this.value += 1;
}
public boolean isAlive() {
return this.value < 10;
}
public String toString() {
return Integer.toString(this.value);
}
}
Here, a "Grower" is a class that can "grow" in some sense, and it has up to 10 growth cycles. If I asked you to change Grower1 so that instead of incrementing a number it grows by appending the character 'a' to the initial string "a" (so, it goes "a" --> "aa" --> "aaa", etc.), you would have to change the code in Main. If you tried to do the same with Grower2, it would be a bit easier, but you'd still have to change the code in Main, although in fewer places. If you did it with Grower3, nothing in Main has to change (because the public members of Grower3 in no way reveal that value
is an integer):
class Main {
public static void main(String[] args) {
// omitted code related to Grower1 & Grower2...
// still works with no changes
Grower3 g3 = new Grower3();
g3.grow();
if (g3.isAlive()) {
System.out.println(g3.toString()); // prints out: aa
}
}
}
// omitted Grower1 & Grower2 classes...
class Grower3 {
private String value = "a";
public void grow() {
this.value += "a";
}
public boolean isAlive() {
return this.value.length() < 10;
}
public String toString() {
return this.value;
}
}
The trick is to figure out how to design the public methods so that you can do this kind of thing.

- 8,428
- 1
- 13
- 20