Running on Java 24-ea+24-2960 (Preview)
Home of The JavaSpecialists' Newsletter

293Canonical Orders

Author: Dr Heinz M. KabutzDate: 2021-09-30Java Version: 17Category: Language
 

Abstract: Should we write "public abstract static class" or "public static abstract class"? And should fields be "final static private" or "private static final"? In this newsletter we explore the canonical order of modifiers in Java.

 

Welcome to the 293rd edition of The Java(tm) Specialists' Newsletter. Most mornings after the school drop, I get to grab a coffee at what must be one of the most efficient coffee bars anywhere. Voula spots me parking my Suzuki Jimny outside, and immediately gets to work grinding my arabica coffee beans. By the time my mask is on and I am waddling into her shop, she has already poured my "diplo espresso, sketo, choris kapaki" (double espresso, black without sugar, without the plastic lid). Yes, I have occasionally spilled my coffee, but it irks me to stick a plastic lid on something I will consume in the next few minutes anyway. The coffee is already rung up on her POS and after a few friendly words, I'm on my way. Most mornings go off without a hitch, but unfortunately Voula occasionally gets days off. On those days we have a hearty exchange trying to explain that yes, I do want a hot coffee, not cold, and no, I do not want sugar, I'm sure of that, and no, I also don't want the plastic lid but thank you so much for asking.

javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.

Canonical Orders

I was reading some Java code the other day and began to notice that the order of the modifiers looked peculiar. Some fields were defined as final private then others as final static private and then others as the more typical private static final. I am so used to reading one particular sequence of modifiers, that this looked strangely messy. Perhaps my German Ordnung genes were kicking in? Or was there a canonical order that was preferred and which I have used for so long that I only notice it when it is not followed?

After digging around in IntelliJ IDEA's code analyzer, I found this inspection: Java -> Code style issues -> Missorted modifiers. It claimed that it would report declarations whose modifiers were not in the canonical preferred order (as stated in the Java Language Specification). Thus there was some order that was apparently preferred, but what was that order?

After searching in the Java Language Specification for a while, I found JLS section 8.3.1, which states that "If two or more (distinct) field modifiers appear in a field declaration, it is customary, though not required, that they appear in the order consistent with that shown above in the production for FieldModifier. Aha, so what are all the possible FieldModifiers?

FieldModifier:
  (one of)
  Annotation public protected private
  static final transient volatile

Thus the annotation should come first, and then the other modifiers in that order. Our code will compile even if we do not follow this canonical order, but it's a bit like leaving the toilet seat up in a shared house. As we will see, the OpenJDK follows this canonical order quite consistently.

Methods have a similar preferred order, defined in JLS section 8.4.3:

MethodModifier:
  (one of)
  Annotation public protected private
  abstract static final synchronized native strictfp

Constructor is a bit easier, because only in the case of an annotation can we have more than one modifier, defined in JLS section 8.8.3:

ConstructorModifier:
  (one of)
  Annotation public protected private

The class also has quite a few modifiers, especially since sealed classes were added. The most common mistake is to write static before abstract. Again, we can find the recommended order in JLS section 8.1.1:

ClassModifier:
(one of)
Annotation public protected private
abstract static final sealed non-sealed strictfp

It is not too difficult to remember most of them. Annotations always come first. Then we have public/protected/private. Next up is abstract, if applicable. Then static and final. The rest is too rare to bother memorizing.

I sent IntelliJ IDEA off to look through the OpenJDK code. It found only 135 variations of this canonical modifier order. That is surprisingly few, considering that the OpenJDK has over 10 millions lines of Java code. The most common deviation was when annotations were not the first modifier, which happened 96/135 times, over 71%. Next up were 18 "static abstract" instead of the more canonical "abstract static". Then 12 public/protected/private after other modifiers. The 9 remaining places had mixed up final / static / native / transient and volatile.

After the OpenJDK, I decided to run the analyzer over the sample code for my Dynamic Proxies in Java book. I found 10 missorted modifiers, always "final static" instead of "static final". Oops. I also ran it over Jetty 10.x and in their 622k LOC did not find any missorted modifiers. Well done Jetty!

I then inspected Spring Framework with its 1.2m LOC. There we found 159 warnings, of which 79 were writing static abstract instead of abstract static, 46 were the annotations not the first modifier, 28 was final static instead of static final, the mistake that I made too and then only 6 had public/protected/final not immediately after the annotation.

Missorted elements in module-info.java

It seems that the module-info.java file also follows a canonical order. I found only one module-info.java file in the OpenJDK that deviated from that slightly. Here is the order that I believe we should use. Always start with requires, so that anyone looking at our module-info.java file immediately sees what modules we depend on. Next we list all requires transitive, followed by requires static. We then show the packages that our module exports generally followed by those exports that are to a specific module. Next we list all the packages that we allow deep reflection on via opens, preferably to a specific module. Lastly we have uses and then provides for the ServiceLoader. The order can be seen in JLS Module Directive:

[open] module some.module.name {
    requires ...

    requires transitive ...

    requires static ...

    exports ...

    exports ... to
      ...
      ...
      ...

    opens ...

    opens ... to
      ...
      ...
      ...

    uses ...

    provides ... with
      ...
      ...
      ...
}

Also, the class names in uses and provides should be fully qualified, thus import statements should not be used.

Kind regards

Heinz

 

Comments

We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)

When you load these comments, you'll be connected to Disqus. Privacy Statement.

Related Articles

Browse the Newsletter Archive

About the Author

Heinz Kabutz Java Conference Speaker

Java Champion, author of the Javaspecialists Newsletter, conference speaking regular... About Heinz

Superpack '23

Superpack '23 Our entire Java Specialists Training in one huge bundle more...

Free Java Book

Dynamic Proxies in Java Book
Java Training

We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.

Java Consulting

We can help make your Java application run faster and trouble-shoot concurrency and performance bugs...