The simple rule:
Interface should be public. Implementation should be private.
When you make a field public (or even protected), you are effectively declaring it as part of the interface. Problem is, it's an implementation detail -- in almost every case, that field means something to your code. Anyone that wants to set it can, but you have to carefully explain how it needs to be set in order to keep the whole thing from crashing and burning. You can't even validate it as it's being set, so you need to validate it every...single...time before you use it, which can kill performance depending on how the validation needs to be done. (Even then, there's no guarantee that the field will stay valid, because you can't even enforce synchronized access to it.) And everyone using your class will have to do the same thing, cause $DEITY only knows what other code has been mucking around with that field and possibly corrupting it.
On top of all that, once it's a field, people are going to write code that expects to use that field. And in the cases where you find you need any of that validation later, you can't just convert a field to a getter/setter without breaking binary compatibility (meaning anyone who used your code will have to recompile everything that used that field in order for it to work again). Do that too many times, and people will be afraid to use your API -- read: you won't have any users.
Getters and setters separate the implementation from the interface. They allow callers to get back something that is definitely valid, and let you make sure that anything going in is definitely valid. This makes things more predictable, more stable. So if you write code that will ever be used after you write it, getters and setters are a good idea.