Controlling the Visibility of Class and Interface in Java
Maintenance is one of the important aspects of software development, and experience has shown that software that maintains its component’s visibility low is more maintainable than one that exposes its component more. You’re not going to know it upfront, but when redesigning the application, you’re going to miss it terribly.
You end up patching and repeating the same errors, as maintaining backward compatibility is a must-have requirement for many applications. You will not do much because the class and interfaces are tightly integrated with a lot of other applications. Java has always prioritized encapsulation, providing access modifiers of support from the very beginning. By making them public, package-private or private provides ways to monitor the visibility of some type, such as class or interface.
Below are some rules to control the visibility:
- A top-level class (a class whose name is the same as the Java source file that contains it) can also be either a public or a private package (without an access modifier) and cannot be a private one. Private, public, or package-private may only be a nesting class.
- A public class is accessible to all and most visible, try to keep public only key interfaces, never let the implementation go public until you believe it’s complete and mature.
- The private type, on the other hand, is less visible, and in Java, only the nested class or interface can be private. You have full control over this class to change its actions with experiences, new technology, tools, and redesign, as it’s least visible.
- Package-private visibility is a clever midway and is also default visibility, there’s no such keyword as package-private, instead if you don’t have any access modifier as Java thinks it’s package-private, and then make it only visible on the same package.
- If the classes and interfaces are only shared within the same package between other classes, make them package-private. As the client is unable to reach them, they are therefore reasonably safe to change.
In addition to decreasing class or interface visibility using the access modifier, based on your runtime environment, there are many other ways to do so. At the component level, such as Websphere, Weblogic, or JBoss in Application Server, an interface class may be proxied or wrapped to reduce external visibility.
No matter what you do, there will still be certain types that need to be exposed to the outside world, but you can always handle them with proxy or wrapper. Although client programs will load proxied implementation classes, an immutable proxy or wrapper would often be obtained.
For example, the Java Servlet API (javax.servlet) getServletContext() returns an implementation of javax.servlet.ServletContext, which is typically an immutable proxy to satisfy the ServletContext framework promises. It is most possible that a separate version of the javax.servlet.ServletContext specification operates on the application server.
It is possible to use a similar pattern in the implementation of other externally accessible interfaces, e.g. Javax.ejb.EJBContext, Javax.ejb.TimerService, ServletRequest, ServletResponse, etc. To support these global interfaces, various application servers can use various applications.
JDK Example of Controlling Visibility of Java Class
EnumSet class is another fascinating example of managing visibility. In order to prevent instantiation, the Java designer made the abstract class and provided factory methods as the only way to create an instance of that class, e.g. Methods from EnumSet.of() or EnumSet.noneOf().
Internally, in the form of RegularEnumSet and JumboEnumSet, they have two separate implementations, which are automatically selected based on the size of the main universe by static factory methods.
For instance, if the number of values in Enum is less than 64, then RegularEnumSet is used, otherwise, the JumboEnumSet instance is returned. The beauty of this design is that package-private means that consumers have no idea about any of these implementations.
Modifier Description Default declarations are visible only within the package (package private) Private declarations are visible within the class only Protected declarations are visible within the package or all subclasses Public declarations are visible everywhere
Private Access Modifier
Main.java:18: error: name has private access in Data d.name = "Programiz"; ^
In the above example, we have declared a private variable named name and a private method named display(). When we run the program, we will get the above error:
Protected Access Modifier
I am an animal
Public Access Modifier:
I am an animal. I have 4 legs.