Saturday, May 26, 2018

Java's String.format Can Be Statically Imported

JDK-8203630 ["Add instance method equivalents for String::format"] postulates that "the argument for implementing String::format as static appears to be that the format methods could be imported statically and thus conduct themselves comparably to C's sprintf." On a thread on the subject, Brandon Yarbrough writes, "by making the method static you can use format in a way that's very familiar and clean-looking to C programmers used to printf()." Yarbrough provides a code example and then concludes, "By using static imports, printfs look almost exactly like they do in C. Awesome!"

When I read in JDK-8203630 about this, I wondered to myself why I had not statically imported String.format when I've used it because it seems obvious to me now to do that. In this post, I look briefly at some personal theories I have considered to explain why I (and many others apparently) have not thought to statically import String.format consistently.

When static imports were introduced with J2SE 5, the new documentation on the feature presented the question, "So when should you use static import?" It answered its own question with an emphasized (I did NOT add the bold), "Very sparingly!" That paragraph then goes on to provide more details about appropriate and inappropriate uses of static imports and the negative consequences of overuse of static imports.

Although the original documentation warned emphatically about the overuse of static imports, their use did seem to increase gradually as developers became more used to them. In 2012, I asked, via blog post, "Are Static Imports Becoming Increasingly Accepted in Java?" I felt at that time that they were becoming increasingly accepted, especially when used in unit testing contexts and in more modern libraries and frameworks focusing on providing "fluent" APIs. Still, somehow, I did not think to consistently apply static imports to my uses of String.format.

I don't use String.format very often, so I thought that perhaps I just didn't get many opportunities to think about this. But, even in my relatively few uses of it, I don't recall ever importing it statically. As I've thought about this more, I've realized that the primary reason I probably don't think about statically importing String.format is the same reason that most developers have not thought about it: most of the popular and readily available online examples of how to use String.format do not use static imports!

When writing a blog or article covering a feature, especially if it's at an introductory level, it can be useful to NOT do things like import statically because the explicitly spelling out of the class name can improve the developer's ability to understand where the methods in the code come from. However, this also means that if a given developer reads numerous articles and posts and none of them show use of static imports, it is easy for that developer to use the API as shown in all those examples without thinking about the possibility of statically importing.

The following are some introductory posts regarding use of String.format. At the time of this writing, they do not demonstrate use of String.format via static import. I want to emphasize that this does not take away from the quality of these resources; in fact, some of them are excellent. This is instead intended as evidence explaining why String.format seems to be seldom statically imported in Java code.

Many of the examples in the above posts use String.format() to generate a String that is assigned to a local variable. In this context, the static import is arguably less valuable than when it is used to format a String within a greater line of code. For example, it is more "fluent" to statically import String.format() so that simply format() can be specified when that formatting takes place in a line of code doing other things beyond simply assigning the formatted string to a local variable.

The main purpose of this blog post is to point out/remind us that we can statically import String.format when doing so makes our code more readable. However, there were some other interesting points made in the short discussion on the OpenJDK core-libs-dev mailing list on this subject that I'll briefly point out here:

  • JDK-8203630 points out how an instance method might make for arguably more readable code in some cases with this example: "This result is %d".format(result);
  • RĂ©mi Forax points out some arguments against adding an instance format method to String:
    • Issues associated with static and instance methods sharing the same name in a class.
      • John Rose adds, "Refactoring static as non-static methods, or vice versa, is a very reasonable design move, but the language makes it hard to do this and retain backward compatibility."
    • Relative slowness of Java's current string interpolation capabilities with provided by String.format
    • Potential of StringConcatFactory for future faster Java string interpolation (see "String concatenation in Java 9 (part 1): Untangling invokeDynamic" for more details on StringConcatFactory).

Whether or not instance format methods come to Java's String, reading about JDK-8203444, JDK-8203630, and the associated mailing list discussion have provided me with some things to think about. If nothing else, I'll definitely be more apt to weigh String.format's performance when considering using it and will be more likely to statically import it when I do use it.

1 comment:

tachjava said...

Nice article on String.format with great examples and appropriate links. Thanks for sharing.