R
As you should know, there are 4 types of visibility in java:publicprivateprotectedpackage-default (this is not a keyword, it is what happens when no modifier is used).In mature and well-designed software projects, the protected and package-default almost never used:In the case of protected, the inheritance has been seen as something bad from a few years here. The reason is that the inheritance introduces a strong subclass coupling to the superclass. When you use fields or methods protected and the superclass depends on them being used in certain ways by the subclasses, you also end up attaching the superclass to your subclasses. This goes on the countermeasure of good practice of object-oriented systems design that prey the weak coupling. With the use of design patterns, it is possible to eliminate all inheritance cases and exchange them by composition except when you have to use third-party libraries that cannot be modified and that provide superclasses that impose inheritance to be used.In the case of package-default, if a class needs to display features selectively for other classes in the same package, but not for the other classes, it is a sign that there is some problem https://en.wikipedia.org/wiki/Cohesion_(computer_science) , https://en.wikipedia.org/wiki/Coupling_(computer_programming) or https://en.wikipedia.org/wiki/Encapsulation_(computer_programming) .So unless you're using a library that imposes you on draconian restrictions, in a well-made project, there are almost no cases where it's a good idea to use protected or package-default. Where they occur and are indeed the best alternative, it will probably be to circumvent some limitation of language. So let's focus on public and private:In the case of fields/attributes that do not have both modifiers static and final, the correct modifier is the private and final point. If you are tempted to use anything other than private in a non-static or notfinal (including forgetting to put the private), you're doing something wrong.The fields that are simultaneously static and final can be public as long as they refer to values of primitive types or immutable objects. Even when private, it is still a good idea that they are primitive values or immutable objects.A class must publish for others, an API (group of fields, methods, builders and internal classes) which details what features it offers to the other classes to be used. The parts of the class that are in this API that it offers others receive the modifier public, and whatever is out of this set, must keep private. A method that represents a complete and important functionality of the class business rule should probably be public. Something that represents a passage of code that was in any method and that was separated into a new method only part to get better organized, probably should be private.For the methods, builders and inner classes, you have to judge whether that is something that interests other classes or not. The class should be made looking to be preached by encapsulation, high cohesion and low coupling, which will help to separate what it offers to the world from what is just an internal technical detail in the way it is implemented. This judgment is subjective and requires a good dose of experience to be done correctly, but most of the time, judging which is the best case is easy, although there are always some that are in the gray zone.From Java 8, interfaces can have static methods and with standard implementations (do not confuse the modifier default employee with visibility package-default, this is not the purpose of the modifier). This helps reduce the need to use protected and package-private. Assess this with the lambdas, and this need is further reduced.Until Java 8, anything that was placed inside one interface it was public, even if the keyword public is not there (if you do not put the modifier public in a method of one interface, the compiler will pretend that the modifier was there, there is no package-default for interface members). From Java 9, interfaces can also have private methods (which must have the modifier private) and that are not inherited by the classes that implement this interface. This change in Java 9 serves to eliminate one of the very few cases where visibility package-default made sense, that was to provide (through auxiliary classes in the same package) features with implementations to methods default or static of the interface that should not be inherited.