The main reason why there is a distinction is because of Visualforce. You cannot access a variable in Visualforce, but you can access a property.
To illustrate this at the most basic level, consider this code:
public class myController {
public String helloWorld = 'Hello, world!';
}
<apex:page controller="myController">
<!-- following line causes a compile error -->
{!helloWorld}
</apex:page>
This code will fail to compile because helloWorld
is a variable, not a property. To fix this, we need to change it to a property:
public class myController {
public String helloWorld { get; set; }
public myController() {
helloWorld = 'Hello, world!';
}
}
So, even though the automatic read-write property may seem superfluous in code, it is actually required in certain contexts. Note that this is not the only way you can expose a variable to Visualforce, but those are outside the scope of the question and this answer.
If a variable will never be exposed directly to Visualforce, then there is no other reason why you'd want to turn it in to a read-write property, since it would just be a waste of code.
Of course, in library code, it might be useful to have read-only or write-only properties, or do constraint checks, etc, so there's plenty of reasons why you might use any of the various permutations of property getters and setters.