Making Java Code Easier to Read (Without Changing it)
Modern JVM languages such as Kotlin, Groovy, Scala and some others offer many language features that let you write code in a more concise and expressive manner. These features include type inference, properties, interpolated string, range and tuple literals, enhanced operators, clojures, implicits, smart casts, and many more.
Even Java (which always used to be very conservative and with good reasons), in its last version (v8) introduced the lambda syntax to make code less verbose yet more expressive.
Prior to Java 8 IntelliJ IDEA had used its folding feature to emulate the lambda syntax to make code more readable:
If you expand or hover the folded code, you’ll see this:
If you use Java 7 or an earlier version, IntelliJ IDEA still folds such code for better readability.
Since I’m personally a big fan of Kotlin but daily have to write a lot of Java, I decided to extend the IDE’s folding features to emulate some other modern languages’ features helping fight verbosity. As a result I built an IntelliJ IDEA plugin. Here in this blog post I’d like to briefly share some of its most interesting features.
Consider this example:
If Java provided interpolated strings, it would look like this:
The plugin emulates exactly that via folding, even when an interpolated string contains expressions:
Notice, the folding doesn’t break the syntax highlighting or code navigation.
Now consider this example:
If we apply the concepts of implicit conversions and enhanced operators, we’ll get the following code:
Still clear but more concise and readable.
Slice operations on strings and lists
Now consider this example:
Here we ask a substring, referring to the length of the string. What if Java provided the slice operation offered by Python? If you enable the corresponding option in the plugin, you’ll get this feature emulated in Java code:
Now consider another example:
Here we use “int” variables to store state. When you read the code, the type itself isn’t always as important as the semantics. Since “final” is not enforced by Java, here all “variables” are mutable.
What if Java had type inference, and, all developers always used “final” properly? Sounds academic but the IDE could emulate that through folding and data flow analysis:
This way the code is far easier to understand.
Now consider this example. Here we iterate over a collection and access both the item and its index:
What if Java supported tuples? Well, our code would become less verbose and still would be readable:
This could be even more concise had we used it along with the previous folding option:
Let’s look at another example, where we iterate over an array but don’t access its items:
Could it be written in a more concise manner had we range literals supported by Java? Well, at least the plugin makes it possible through emulation:
Equals and compareTo
Now look at this example:
This is what Java forces us to write because of the “referential” equality. What if Java used the “structural” equality for operators? This would make the code a bit shorter and somewhat clearer:
The same approach works for negated equality:
What about compareTo?
Again, if Java had enhanced operators, we could simply write this:
Well, now the plugin can emulate it for you.
Look at the code below. Looks familiar, doesn’t it?
This syntax is verbose because of the way properties work in Java: every property is accessed through its getter or setter.
What if Java allowed to access properties the Kotlin way?
It’s 30% less code and even more readable. If you prefer it this way, you can enable the corresponding option in the plugin. Of course, the same works for setters as well:
What if Java allowed enhanced operators and Collection provided those for add, addAll, remove and removeAll methods? Look at this code:
The plugin emulates these operators to make the semantics a bit more clear:
What if List had the first() and last() methods (e.g. as other JVM languages do)?
Isn’t it more readable?
Imagine when we check if an instance of an object is of a specific type, and if so, we access one its type-specific members (quite popular case, by the way):
If Java had smart casts like Kotlin, we would have clearer, more compact code:
Last but not least, consider this example:
Here we use the Java’s elvis expression to check for null. Could we emulate the safe calls provided by Groovy and Scala to make it more expressive? Well, yes:
Note, all the foldings mentioned above are optional in the plugin and can be configured in the preferences.
If you decide to try any of these folding, install this plugin. Meanwhile I’ll be very happy to hear your thoughts on the matter.
Bug reports as well as feature requests would be very appreciated in the issue tracker.
Develop with Pleasure!