Java Modifiers

A summary of main modifiers in Java SE 18. Source: Adapted from Gosling et al. 2022.
A summary of main modifiers in Java SE 18. Source: Adapted from Gosling et al. 2022.

A modifier is a programming construct in Java used to modify/refine/restrict a declaration. With modifiers, developers can restrict access, limit class instantiation to a single instance, disallow value modification, control persistent storage, configure sharing of variables across threads, and more. Modifiers can be applied to classes, class fields, class methods, class constructors and interfaces.

Most modifiers are keywords, meaning that developers can't use them as identifiers. Modifiers sealed and non-sealed are not keywords.

In some cases, default modifiers are applied when modifiers are not explicitly specified by the developer. However, it's a good practice to explicitly specify modifiers.

Annotations are considered as modifiers but these are not covered in this article.

Discussion

  • Could you explain Java's access modifiers?

    Access to a class, interface, field, method or constructor can be controlled via access modifiers. Any one of these three can be used:

    • public: access to everyone
    • protected: access to subclasses anywhere plus everyone within the package
    • private: access limited to the class

    When no access modifier is specified, by default access is restricted to within the package; that is, anyone within the package can access. This is also called package-private. The Java Language Specification (section 6.6) gives more details.

    Broadly, there are two levels of access control: (a) top level: public or package-private; (b) member level: public, protected, package-private, private. Top level applies to classes and interfaces. Member level applies to members of classes and interfaces, including nested classes and interfaces.

    As a best practice, members should be private unless there's a need to expose them. This hides the internal implementation. Except for constants, avoid public fields. Access to top level public classes and interfaces can be restricted to the module by not exporting them.

  • Could you explain Java's static modifier?
    Static variables are shared by all instances. Source: Baeldung 2017.
    Static variables are shared by all instances. Source: Baeldung 2017.

    There are use cases where we wish that all instances of a class share fields rather than have separate copies. Logging is an example where multiple instances log via the same logger. Another example is the method public static main(String[] args) that forms the entry point for any program. The JVM starts execution from this method even when no instance has been created. The static modifier enables us to do this.

    Nested classes can be static. Local or anonymous classes can't be static. Nested enum classes and nested record classes are implicitly static.

    A static field/method is also called a class variable/method. In a static context, the use of this and super are not allowed. Static fields can be initialized using field initializers or static initializers that may include one or more blocks of code.

    A nested interface, member or local, is implicitly static.

    Static fields/methods are preferably accessed via the class name. Static methods can't be overridden since they're resolved at compile time. Static methods can't be abstract.

  • Which modifiers affect inheritance in Java?

    A subclass or subinterface can extend or implement from another class or one or more interfaces. This is one way by which Java enables code reuse. However, modifiers final, sealed and non-sealed help developers control inheritance. These modifiers may be used towards a more maintainable code. For example, a Vehicle class may state that only Car and Truck subclasses can extend it. This avoids the inelegant use of instanceof or if-else statements. Thus, runtime checks are replaced with compile-time checks.

    A class is declared final when it's desired that no subclass can extend it. It's methods can't be overridden. A final class can't be abstract.

    A class/interface is declared sealed if it specifies all known subclasses/subinterfaces. The subclasses/subinterfaces themselves may be sealed; or non-sealed if they can be freely extended. A permitted subclass must be itself be declared as final, sealed or non-sealed.

  • Could you explain the abstract method modifier?

    Sometimes we wish to share code among closely related classes. But what's common among these classes is incomplete in the sense that their superclass can't be instantiated. An example is the area() method of class Shape. Subclasses Circle and Rectangle can and should implement this method but Shape itself is too abstract to implement it.

    The abstract modifier is applicable to classes, methods and interfaces. However, since every interface is implicitly abstract (since classes are expected to implement an interface), explicit use of this modifier for interfaces is obsolete.

    A class with at least one abstract method must itself be declared abstract. A class that partially implements an interface must be declared abstract. A subclass of an abstract class itself can be abstract. In all cases, abstract classes can be subclassed but can't be instantiated. An abstract class can be sealed but not made final.

  • Could you explain transient and volatile field modifiers?

    Sometimes there's a need to store an object in a persistent manner, such as into a database or a disk file. Java's java.io.Serializable class helps us to serialize the object for storage. But what if there are some fields that we don't wish to save? This is where the transient modifier can be used. Fields with this modifier are ignored for storage.

    Java allows multiple threads to share variables. Using locks, developers can enforce mutual exclusion on those shared variables. However, the use of volatile modifier gives developers an alternative approach. The Java Memory Model ensures that all threads see a consistent value without extra effort from developers. A final variable can't also be declared volatile.

  • Could you explain native and synchronized method modifiers?
    Illustrating the use of synchronized modifier. Source: Adapted from Gosling et al. 2022, sec. 8.4.3.6.
    Illustrating the use of synchronized modifier. Source: Adapted from Gosling et al. 2022, sec. 8.4.3.6.

    Sometimes we wish to reuse functionality already implemented in another language. This may be legacy code, platform-dependent code or code written for better performance or low-level hardware access. The native modifier tells the Java compiler that the method is implemented elsewhere. No method body is supplied. Instead the method declaration ends with a semicolon. Native code is interfaced to the JVM via Java Native Interface (JNI).

    The synchronized modifier helps developers write methods that can run concurrently in a multi-threaded environment. For example, suppose one method puts items into a queue or updates a variable, and another method executing in a concurrent thread reads from the queue or variable. With the use of synchronized modifier, method executions will not get pre-empted.

    Under the hood, a synchronized method acquires a monitor. For a class method, the monitor is associated with the class. For an instance method, it's associated with this.

  • Could you explain the Modifier class?

    Java's Modifier class is part of the java.lang.reflect package. Reflection allows a program to get information about classes at runtime. Via static methods and constants, the Modifier class gives information about class and method access modifiers. Examples of constants are ABSTRACT, FINAL and STATIC. Examples of methods are isAbstract(int), isFinal(int), isStatic(int), classModifiers() and methodModifiers().

    An example usage would be to call the getModifiers() methods on an instance of java.lang.Class, java.lang.reflect.Field, java.lang.reflect.Method or java.lang.reflect.Constructor. The returned value can be processed using the java.lang.reflect.Modifier class.

Milestones

Jan
1996

Java 1.0 is released. This release includes access modifiers public, protected and private; class modifiers abstract and final; field modifiers static, final, transient and volatile; method modifiers abstract, static, final, native and synchronized; and interface modifier abstract. The use of abstract modifier for interfaces is redundant since interfaces are abstract by definition.

Dec
1998

Java 1.2 is released. This adds the modifier strictfp to enforce strict floating-point semantics regardless of the platform. In Java SE 17 (September 2021), this modifier is made obsolete since by then processors support SSE2 (Streaming SIMD Extensions 2) that natively supports strict floating-point semantics.

Sep
2017

Java SE 9 is released. For better modularity, the module concept is introduced. A module's packages are accessible to other modules only if the module exports them and modules that use them explicitly require them. This refines the semantics of the top level public access modifier and nested public and protected modifiers. Moreover, runtime-only access to packages can be achieved via opens and open directives.

Sep
2020

Java SE 15 is released. This adds modifiers sealed and non-sealed to give developers control on inheritance hierarchy. Classes and interfaces can be controlled with these modifiers. The permits clause specifies which classes and interfaces can extend or implement the current class or interface.

References

  1. Baeldung. 2017. "A Guide to the Static Keyword in Java." Baeldung, October 27. Updated 2021-11-24. Accessed 2022-05-03.
  2. Baeldung. 2018. "Guide to JNI (Java Native Interface)." Baeldung, May 27. Updated 2021-12-31. Accessed 2022-05-04.
  3. Baeldung. 2019. "The Java Native Keyword and Methods." Baeldung, January 1. Updated 2019-10-09. Accessed 2022-05-04.
  4. Deitel, Paul. 2017. "Understanding Java 9 Modules." Excerpt from Java Magazine, September/October. Accessed 2022-05-03.
  5. French, Tim. 2013. "Java Primer." CITS2200: Data Structures and Algorithms, The University of Western Australia. Accessed 2022-05-03.
  6. Gosling, James, Bill Joy, and Guy Steele. 1996. "The Java™ Language Specification." Addison-Wesley. Accessed 2022-05-03.
  7. Gosling, James, Bill Joy, Guy Steele, Gilad Bracha, Alex Buckley, Daniel Smith, and Gavin Bierman. 2022. "The Java® Language Specification." Java SE 18 Edition, Oracle America, Inc., February 23. Accessed 2022-05-01.
  8. Krill, Paul. 2021. "JDK 17: The new features in Java 17." InfoWorld, September 14. Accessed 2022-05-03.
  9. Minh, Nam Ha. 2022. "Java SE versions history." CodeJava. Accessed 2022-05-03.
  10. OWASP. 2022. "Poor Logging Practice." OWASP. Accessed 2022-05-03.
  11. Oracle. 2020. "3. Sealed Classes." Java Language Updates, Java SE 15, Oracle, September 14. Accessed 2022-05-03.
  12. Oracle. 2022a. "Java Language Keywords." The Java™ Tutorials, Oracle. Accessed 2022-05-02.
  13. Oracle. 2022b. "Examining Class Modifiers and Types." The Java™ Tutorials, Oracle. Accessed 2022-05-02.
  14. Oracle. 2022c. "Retrieving and Parsing Field Modifiers." The Java™ Tutorials, Oracle. Accessed 2022-05-02.
  15. Oracle. 2022d. "Retrieving and Parsing Method Modifiers." The Java™ Tutorials, Oracle. Accessed 2022-05-02.
  16. Oracle. 2022e. "Retrieving and Parsing Constructor Modifiers." The Java™ Tutorials, Oracle. Accessed 2022-05-02.
  17. Oracle. 2022f. "Controlling Access to Members of a Class." The Java™ Tutorials, Oracle. Accessed 2022-05-03.
  18. Oracle. 2022g. "Lesson: A Closer Look at the "Hello World!" Application." The Java™ Tutorials, Oracle. Accessed 2022-05-03.
  19. Oracle. 2022h. "Abstract Methods and Classes." The Java™ Tutorials, Oracle. Accessed 2022-05-03.
  20. Oracle. 2022i. "Class Modifier." Documentation, Java SE 18, Oracle. Accessed 2022-05-02.
  21. Oracle. 2022j. "Package java.lang.reflect." Documentation, Java SE 18, Oracle. Accessed 2022-05-04.
  22. Programming Guide. 2022. "Java: Abstract interfaces and abstract interface methods." Programming Guide. Accessed 2022-05-03.
  23. Strmecki, Daniel. 2021. "Sealed Classes and Interfaces in Java 15." Baeldung, July 8. Accessed 2022-05-03.

Further Reading

  1. Oracle. 2022f. "Controlling Access to Members of a Class." The Java™ Tutorials, Oracle. Accessed 2022-05-03.
  2. Baeldung. 2017. "A Guide to the Static Keyword in Java." Baeldung, October 27. Updated 2021-11-24. Accessed 2022-05-03.
  3. Oracle. 2020. "3. Sealed Classes." Java Language Updates, Java SE 15, Oracle, September 14. Accessed 2022-05-03.
  4. Oracle. 2022h. "Abstract Methods and Classes." The Java™ Tutorials, Oracle. Accessed 2022-05-03.

Article Stats

Author-wise Stats for Article Edits

Author
No. of Edits
No. of Chats
DevCoins
3
0
1276
1384
Words
1
Likes
3103
Hits

Cite As

Devopedia. 2022. "Java Modifiers." Version 3, May 4. Accessed 2023-11-12. https://devopedia.org/java-modifiers
Contributed by
1 author


Last updated on
2022-05-04 12:04:13