As stated by others, private variables are good to avoid miss-usages leading the object into an inconsistent status and hard to track bugs and unforeseen exceptions.
But in the other hand, what has been mostly ignored by the others is about protected fields.
An extended sub-class will have full access to protected fields, making the object as fragile as if such fields were public, but that fragility is limited to the extending class it-self (unless it exposed such fields even more).
So, public fields are hard to be considered good, and to the date the only reason to use them is for classes used as configuration parameter (a very simple class with many fields and no logic, so that class is passed as a parameter alone to some method).
But in the other hand, private fields lowers the flexibility of your code to other users.
Flexibility vs Troubles, pros and cons:
Objects instantiated by your code in the vanilla class with protected fields are safe and are your sole responsibility.
In the other hand, objects extending your class with protected fields, instantiated by the users of your code, are their responsibility, not yours.
So, not well documented protected fields/methods, or if the users do not really understand how such fields and methods should be used, have a good chance of causing unnecessary trouble to themselves and to you.
In the other hand, making most things private will lower the users flexibility, and may even put them away looking for maintained alternatives, as they may not want to create and maintain a fork just to have things happen their way.
So, a good balance between private, protected and public is what really matters.
Now, to decide between private and protected is the real problem.
When to use protected?
Everytime you understand a field can be highly flexible, it should be coded as protected.
That flexibility is: from becoming null (where null is always checked and recognized as a valid state not throwing exceptions), to having constraints before being used by your class ex. >= 0, < 100 etc, and automatically fixed for over/under-flowed values, throwing at most a warning message.
So, for such protected field you could create a getter and only use it (instead of direcly using the field variable), while other users may not use it, in case they want more flexibility to their specific code, in my example could be like: if they want negative values to work fine at their extended class.